#mongodb #aggregation_framework #mongodb_query
Мне нужно получить массив от пользователя и сделать выборку из базы по следующему принципу: если полученный массив такой animals = ['cat', 'dog', 'penguin'] то мне нужны документы где animals = ['cat', 'dog', 'penguin'] animals = ['cat', 'dog'] animals = ['cat' 'penguin'] и т.д. Подскажите, пожалуйста, как вообще называются такие выборки и как их правильно делать в mongodb.
Ответы
Ответ 1
Если запрос достаточно сложный, и базовых средств либо знаний не хватает, то всегда можно воспользоваться механизмом $where. То есть можно написать сложную логику получения данных, включая if-ы, и вернуть результат, чего в обычных базах данных добиться очень и очень сложно (имею в виду условия и циклы внутри SQL-запросов). Синтаксис прост — в качестве параметра передаётся функция: db.foo.find({$where : функция}) При этом используется объект (переменная) this, по сути — курсор, у которой можно получать свойства. Функция должна вернуть true или false, что означает, попадёт строка в выборку или нет. Вот пример из википедии: db.foo.find({$where : function() { return this.x == this.y; }}) При этом также можно использовать вложенные OR или AND, как в классических SQL-запросах: db.foo.find({$where : function() { if((this.cost>5 && this.cost<10 )|| (this.is_hidden != 1) || (this.link == this.url)){ return true; } return false; }}) Таким образом, курсор пробегает по базе, и выполняет проверки. разумеется, всё это можно ограничивать лимитами на количество строк, $where — всего лишь ключ в массиве параметров запроса. Необходимо понимать, что это всё-таки медленне, чем обычные запросы, но всё равно достаточно быстро. скопировано отсюда по наводке из комментария автора вопроса.Ответ 2
Я полагаю, у вас есть следующие документы в вашей коллекции. { "_id" : ObjectId("56ac7281ebc094e3677b809f"), "animals" : [ "rat", "cat" ] }, { "_id" : ObjectId("56ac7281ebc094e3677b80a0"), "animals" : [ "dog", "cat", "penguin" ] }, { "_id" : ObjectId("56ac7281ebc094e3677b80a1"), "animals" : [ "dog" ] }, { "_id" : ObjectId("56ac7281ebc094e3677b80a2"), "animals" : [ "cat", "dog" ] }, { "_id" : ObjectId("56ac7281ebc094e3677b80a3"), "animals" : [ "dog", "penguin" ] } и массив "animals": var animals = [ "cat", "dog", "penguin" ]; Лучший способ это делать это используя .aggregate() метод который обеспечивает доступ к агрегации цепочке. Первый этап в цепочке это $match где вы отфильтроваете документы, которые не имеют какой-либо элемента в массиве "animals". Это также уменьшает количество документов, которые будут обрабатываться в следующей стадии. Следующий и последний этап — это $redact. Здесь нужно использовать оператор $setIsSubset точно делает что мы хотим; он возврашает true если все элементы первого множество появляются во втором множество, в том числе, когда первый множеств равен второй; и также потому MongoDB не позволяет использовать $in в $cond. Конечно $$KEEP и $$PRUNE являются системные переменные. db.collection.aggregate([ { "$match": { "animals": { "$in": animals } } }, { "$redact": { "$cond": [ { "$setIsSubset": [ "$animals", animals ] }, "$$KEEP", "$$PRUNE" ] }} ]) Это запрос возврашает следующий результат: { "_id" : ObjectId("56ac7281ebc094e3677b80a0"), "animals" : [ "dog", "cat", "penguin" ] } { "_id" : ObjectId("56ac7281ebc094e3677b80a1"), "animals" : [ "dog" ] } { "_id" : ObjectId("56ac7281ebc094e3677b80a2"), "animals" : [ "cat", "dog" ] } { "_id" : ObjectId("56ac7281ebc094e3677b80a3"), "animals" : [ "dog", "penguin" ] } Здесь вам не нужно использовать оператор $where поскольку он вызовет падение производительности. $where evaluates JavaScript and cannot take advantage of indexes. Therefore, query performance improves when you express your query using the standard MongoDB operators (e.g., $gt, $in). In general, you should use $where only when you can’t express your query using another operator. If you must use $where, try to include at least one other standard query operator to filter the result set. Using $where alone requires a table scan. Конечно $redact не использует индексы. Он даже делает сканирования все документы в коллекции но более лучше.
Комментариев нет:
Отправить комментарий