mongodb – выполнить подзапрос

Вопрос: документ: { "_id":1, "id":1, "list" : [ { "lv" : 1 , "id":1}, {"lv" : 2 , "id":2} ] } Я хочу найти find ({"_ id": 1}, {"id": 1, "list.lv": 1}), но ограничить {"list.lv": 1} дополнительным условием: "list.id = Я бы". Это означает, что я хочу только получить "id" и "list.lv" часть первого элемента

Вопрос:

документ:

{ «_id»:1, «id»:1, «list» : [ { «lv» : 1 , «id»:1}, {«lv» : 2 , «id»:2} ] }

Я хочу найти find ({“_ id”: 1}, {“id”: 1, “list.lv”: 1}), но ограничить {“list.lv”: 1} дополнительным условием: “list.id = Я бы”. Это означает, что я хочу только получить “id” и “list.lv” часть первого элемента в списке, потому что его “list.id” == “id” == 1

Обычно значение условия предоставляется в коде, но в этом примере это значение находится в документе. SQL делает это путем подзапроса или таблицы соединений. Поддерживает ли mongodb это в одном запросе? И как записать его в драйвере c++?

Согласно ответу, добавьте код c++:

mongo::BSONObj res; std::vector<mongo::BSONObj> pipeline; pipeline.push_back(BSON(«$match»<<BSON(«_id»<<1))); pipeline.push_back(BSON(«$unwind»<<«$list»)); mongo::BSONArrayBuilder ab; ab<<«$id»<<«$list.id»; pipeline.push_back(BSON(«$project»<<BSON(«id»<<1<<«list.lv»<<1<<«equalsFlag»<<BSON(«$subtract»<<ab.arr())))); pipeline.push_back(BSON(«$match»<<BSON(«equalsFlag»<<0))); pipeline.push_back(BSON(«$project»<<BSON(«id»<<1<<«list.lv»<<1))); conn->runCommand(«db_name», BSON( «aggregate» << «collection_name» << «pipeline» << pipeline ), res); std::cout<<res[«result»].Array()[0].Obj().getObjectField(«list»).getIntField(«lv»); Лучший ответ:

Если у меня возник вопрос, попробуйте выполнить этот основной запрос на основе совокупности, чтобы выполнить то, что вам нужно:

db.collectionName.aggregate( {«$match» : {«_id» : 1 }}, {«$unwind» : «$list»}, {«$project» : {«id»:1, «list.lv» : 1, «equalsFlag» : {«$subtract» : [«$id», «$list.id»]}}}, {«$match» : {«equalsFlag» : 0}}, {«$project» : {«id»: 1, «list.lv» : 1}})

Позвольте мне объяснить это более подробно. Важно отфильтровать как можно больше документов. Мы можем сделать это с помощью первого $ match. Обратите внимание, что если мы сделаем {“_id”: 1} фильтр в конце конвейера, манго не сможет использовать для него индекс. $ unwind превратит каждый элемент массива списка в отдельный документ. Затем нам нужно сравнить два поля. Я не знаю, какой простой способ сделать это, кроме $ where, но мы не можем использовать его с общей структурой. К счастью, как id, так и list.id являются числовыми, поэтому мы можем $ вычесть один из другого, чтобы убедиться, что они равны, “equalsFlag”: {“$ subtract”: [“$ id”, “$ list.id”]}. Если они равны, equalsFlag будет равно 0. Поэтому мы просто добавляем новый $ match для получения документов, где id = list.id и, наконец, чтобы исключить поле equalsFlag из результатов, у нас есть еще один $ project.

Я не парень C++, но я уверен, что драйвер C++ поддерживает агрегатную структуру как большинство других драйверов. Поэтому просто перейдите к некоторым примерам, чтобы преобразовать этот собственный запрос в C++. Это должно быть довольно легко, по крайней мере, для С#.

EDIT: C++ код от jean, чтобы завершить ответ

mongo::BSONObj res; std::vector<mongo::BSONObj> pipeline; pipeline.push_back(BSON(«$match»<<BSON(«_id»<<1))); pipeline.push_back(BSON(«$unwind»<<«$list»)); mongo::BSONArrayBuilder ab; ab<<«$id»<<«$list.id»; pipeline.push_back(BSON(«$project»<<BSON(«id»<<1<<«list.lv»<<1<<«equalsFlag»<<BSON(«$subtract»<<ab.arr())))); pipeline.push_back(BSON(«$match»<<BSON(«equalsFlag»<<0))); pipeline.push_back(BSON(«$project»<<BSON(«id»<<1<<«list.lv»<<1))); conn->runCommand(«db_name», BSON( «aggregate» << «collection_name» << «pipeline» << pipeline ), res); std::cout<<res[«result»].Array()[0].Obj().getObjectField(«list»).getIntField(«lv»);

Надеюсь, поможет!

Оцените статью
Добавить комментарий