Документ возврата совокупного запроса MongoDB, основанный на запросе совпадения и значениях приоритета - PullRequest
1 голос
/ 07 апреля 2020

В коллекции mongodb у меня есть следующие документы:

{"id":"1234","name":"John","stateCode":"CA"}
{"id":"1234","name":"Smith","stateCode":"CA"}
{"id":"1234","name":"Tony","stateCode":"GA"}
{"id":"3323", "name":"Neo","stateCode":"OH"}
{"id":"3323", "name":"Sam","stateCode":"US"}
{"id":"4343","name":"Bruce","stateCode":"NV"}

Я пытаюсь написать агрегированный запрос mon go, который выполняет следующие действия:

  • на основе соответствия в id поле
  • Дайте больший приоритет документу, имеющему значения, отличные от "NV" или "GA" в поле stateCode.

    Если все документы имеют значения «NV» или «GA», игнорируйте приоритет. Если у какого-либо документа есть stateCode, отличный от "NV" или "GA", верните этот документ.

Пример 1:

id = "1234"

then return 

{"id":"1234","name":"John","stateCode":"CA"}
{"id":"1234","name":"Smith","stateCode":"CA"}

Пример 2 :

id = "4343"

then return

{"id":"4343","name":"Bruce","stateCode":"NV"}

Не могли бы вы помочь с запросом, чтобы добиться этого.

Я пытался с запросом, но я застрял с ошибкой:

Failed to execute script.

Error: command failed: {
    "ok" : 0,
    "errmsg" : "input to $filter must be an array not string",
    "code" : 28651,
    "codeName" : "Location28651"
} : aggregate failed

Запрос :

db.getCollection('emp').aggregate([{$match:{
            'id': "1234"
        }
},
{
      $project: {
         "data": {
            $filter: {
               input: "$stateCode",
               as: "data",
               cond: { $ne: [ "$data", "GA" ],$ne: [ "$data", "NV" ] }
            }
         }
      }
   }

])

1 Ответ

2 голосов
/ 07 апреля 2020

Я действительно рекомендую вам разделить это на 2 запроса, сначала попробуйте найти документы с другим кодом состояния, а если это не удастся, то получите остальные.

С учетом сказанного здесь работает рабочий конвейер, который делает это в one go, из-за того, что мы не можем знать заранее, является ли условие истинным или нет, нам нужно выполнить итерацию всех документов, которые соответствуют id, этот факт делает его ОЧЕНЬ неэффективным в случае совместного использования id по многим документам, если это невозможно, то использовать этот конвейер можно.

db.getCollection('emp').aggregate([
    {
        $match: {
            'id': "1234"
        }
    },
    {   //we have to group so we can check
        $group: {
            _id: null,
            docs: {$push: "$$ROOT"}
        }
    },
    {
        $addFields: {
            highPriorityDocs: {
                $filter: {
                    input: "$docs",
                    as: "doc",
                    cond: {$and: [{$ne: ["$$doc.stateCode", "NV"]}, {$ne: ["$$doc.stateCode", "GA"]}]}
                }

            }
        }
    },
    {
        $project: {
            finalDocs: {
                $cond: [ // if size of high priority docs gt 0 return them.
                    {$gt: [{$ize: "$highPriorityDocs"}, 0]},
                    "$highPriorityDocs",
                    "$docs"
                ]
            }
        }
    },
    {
        $unwind: "$finalDocs"
    },
    {
        $replaceRoot: {newRoot: "$finalDocs"}
    }
])

Последние два этапа - просто восстановить исходную структуру, вы можете удалить их, если вам это не важно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...