Хорошо, здесь есть несколько вещей. У меня есть две коллекции: test и test1. Документы в обеих коллекциях имеют поле массива (теги и теги1 соответственно), который содержит некоторые теги. Мне нужно найти пересечение этих тегов. и также извлекают весь документ из коллекции test1, если совпадает хотя бы один тег.Пересечение массива в MongoDB
> db.test.find();
{
"_id" : ObjectId("5166c19b32d001b79b32c72a"),
"tags" : [
"a",
"b",
"c"
]
}
> db.test1.find();
{
"_id" : ObjectId("5166c1c532d001b79b32c72b"),
"tags1" : [
"a",
"b",
"x",
"y"
]
}
> db.test.find().forEach(function(doc){db.test1.find({tags1:{$in:doc.tags}})});
Удивительно, но это ничего не возвращает. Однако, когда я пытаюсь использовать один документ, он работает:
> var doc = db.test.findOne();
> db.test1.find({tags1:{$in:doc.tags}});
{ "_id" : ObjectId("5166c1c532d001b79b32c72b"), "tags1" : [ "a", "b", "x", "y" ] }
Но это часть того, что мне нужно. Мне также нужно пересечение. Так что я попытался это:
> db.test1.find({tags1:{$in:doc.tags}},{"tags1.$":1});
{ "_id" : ObjectId("5166c1c532d001b79b32c72b"), "tags1" : [ "a" ] }
Но он вернулся только «а», тогда как «а» и «б» оба были в tags1. Возвращает ли позиционный оператор только первое совпадение? Кроме того, использование $in
не даст мне перекрестка. Как я могу получить пересечение (должен возвращать «a» и «b»), независимо от того, какой массив сравнивается с другим.
Теперь говорят, что есть оператор, который может это сделать ..
> db.test1.find({tags1:{$intersection:doc.tags}},{"tags1.$":1});
{ "_id" : ObjectId("5166c1c532d001b79b32c72b"), "tags1" : [ "a", "b" ] }
Мое требование, мне нужно весь массив tags1 PLUS это пересечение, в том же запросе, как это:
> db.test1.find({tags1:{$intersection:doc.tags}},{"tags1":1, "tags1.$":1});
{ "_id" : ObjectId("5166c1c532d001b79b32c72b"), "tags1": [ "a", "b", "x", "y" ],
"tags1" : [ "a", "b" ] }
Но это недопустимый json. Возможно ли переименование ключа, или это возможно только через структуру агрегации (и через разные коллекции?)? Я попробовал вышеуказанный запрос с $in
. Но он вел себя так, как будто он полностью проигнорировал проекцию "tags:1"
.
PS: Я собираюсь иметь как минимум 10 тыс. Документов в test1 и очень мало (< 10) в тесте. И этот запрос находится в режиме реального времени, поэтому я хочу избежать mapreduce :)
Спасибо за любую помощь!
Чтобы прокомментировать ваш первый вопрос, «db.test1.find ({tags1: {$ in: doc.tags}})« вернет курсор. Чтобы напечатать на экране, вы должны добавить что-то вроде следующего для второго find: .forEach (function (doc) {print (tojson (doc));}) –
Спасибо @JamesWahlin! Я знал, что это что-то глупое: P Ваш быстрый комментарий позволил мне хотя бы продолжить поиск решения. –