Поиск нескольких полей для нескольких значений в MongoDB

У меня есть коллекция MongoDB, где определенная строка может появляться в любом из нескольких полей:

{"_id":1, "field1":"foo","field2":"bar","field3":"baz", "otherfield":"stuff"},
{"_id":2, "field1": "bar", "field2": "baz", "field3": "foo", "otherfield":"morestuff"},
{"_id":3, "field1": "baz", "field2": "foo", "field3": "bar", "otherfield":"you get the idea"}

Мне нужно запросить, чтобы я возвращал все записи, где любой из множества полей равен любому значению в массиве... в основном, если у меня есть ["foo","bar"], мне нужно, чтобы он соответствовал любому из этих строки находятся в поле1 или поле2 (но не какое-либо другое поле).

Очевидно, я могу сделать это с помощью серии нескольких запросов

db.collection.find({"field1":{"$in":["foo","bar"]}}) db.collection.find({"field2":{"$in":["foo","bar"]}})

и т.д., и я также сделал очень большой $или запрос, который объединяет их все вместе, но он кажется слишком неэффективным (моя фактическая коллекция должна соответствовать любой из 15 строк, которые могут встречаться в любом из 9 полей)... но я все еще новичок в nosql DB и не уверен в лучшей парадигме, которую мне нужно использовать здесь. Любая помощь приветствуется.

Ответ 1

Нашел еще один ответ, просмотрев документацию, которая, кажется, попала в сладость - текстовые индексы.

db.collection.ensureIndex({"field1":"text","field2":"text"})
db.records.runCommand("text",{search:"foo bar"})

Когда я запускаю свой фактический запрос со многими другими строками и полями (и около 100 000 записей), подход $или/$занимает 620 миллисекунд, тогда как текстовый индекс занимает 131 миллисекунду. Единственным недостатком является то, что в результате он возвращает другой тип документа; к счастью, фактические документы являются параметрами каждого объекта результата.

Спасибо тем, кто нашел время, чтобы сделать предложения.

Ответ 2

попробуйте

db.collection.find(
    // Find documents matching any of these values
    {$or:[
        {"field1":{"$in":["foo","bar"]}},
        {"field2":{"$in":["foo","bar"]}}
    ]}
)

также относятся к question

Ответ 3

Я собирал все соответствующие поля в одном поле (т.е. collected), добавляя их значения, такие как

"foo:field1", 
"bar:field2", 
"baz:field3",  
"stuff:otherfield", 
"bar:field1", 
"baz:field2"
...

в это поле.

Если вы ищете bar существующий в любом поле, вы можете использовать:

db.collection.find( { collected: { $regex: "^bar" } }, ... );

Ваш пример в вопросе будет выглядеть так:

db.collection.find( collected: { { $all: [ "foo:field1", "foo:field2", "bar:field1", "bar:field2" ] } }, ... );