Поиск нескольких полей для нескольких значений в 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" ] } }, ... );