Запрос агрегации MongoDB 4.2 для применения фильтра на вторичном уровне - PullRequest
1 голос
/ 29 февраля 2020

Я новичок в mon go и выполняю PO C, имея возможность запросить документ для получения только значений c, определяемых локалью.
Вкратце: объект topLevel имеет подтипы, каждое из которых имеет

  • 0 или 1 описание для данной локали
  • 0 или более альтернативных описаний для данной локали
  • имя и идентификатор

Я хочу иметь возможность получить все подтипы объекта topLevel, которые имеют описание для указанной локали (это я могу сделать). Однако я хочу получить только altDescriptions для этой локали, игнорируя altDescriptions в других locales.

Ex объект topLevel:

{
    "_id" : 1,
    "name" : "top level",
    "subtypes" : [ 
        {   "id" : 21,
            "name" : "child type 1",
            "description" : [ { "text" : "type 1 en_US", "locale" : "en_US" }, 
                              { "text" : "type 1 fr_FR", "locale" : "fr_FR" }, 
                              { "text" : "type 1 es_ES", "locale" : "es_ES" }],
            "altDescriptions" : [ { "name" : "type 1 alt 1 en_US", "locale" : "en_US" }, 
                                  { "name" : "type 1 alt 2 en_US", "locale" : "en_US" }, 
                                  { "name" : "type 1 alt 3 en_US", "locale" : "en_US" }, 
                                  { "name" : "type 1 alt 1 fr_FR", "locale" : "fr_FR" }]
        }, 
        {   "id" : 22,
            "name" : "child type 2",
            "description" : [ { "text" : "type 2 en_US", "locale" : "en_US"} ],
            "altDescriptions" : [ { "name" : "type 2 alt fr_FR", "locale" : "fr_FR" }]
        }, 
        {   "id" : 23,
            "name" : "child type 3",
            "description" : [ { "text" : "type 3 fr_FR", "locale" : "fr_FR"}],
            "altDescriptions" : [ { "name" : "type 3 alt en_US", "locale" : "en_US" }]
        }
    ]
}
```
My query:
```
db.topLevel.aggregate({$unwind: '$subtypes'}, {$unwind: '$subtypes.description'}, 
                      {$match: {'subtypes.description.locale' : 'en_US'}}, 
                      {$project: { type : '$subtypes'}}, {$sort: {'type.description.text' : 1}});
```
returns
```
{ "_id" : 1,
  "type" : { "id" : 21,
             "name" : "child type 1",
             "description" : { "text" : "type 1 en_US", "locale" : "en_US" },
             "altDescriptions" : [ { "name" : "type 1 alt 1 en_US", "locale" : "en_US" },
                                   { "name" : "type 1 alt 2 en_US", "locale" : "en_US" },
                                   { "name" : "type 1 alt 3 en_US", "locale" : "en_US" },
                                   { "name" : "type 1 alt 1 fr_FR", "locale" : "fr_FR" }]
           }
}
{ "_id" : 1,
  "type" : { "id" : 22,
             "name" : "child type 2",
             "description" : { "text" : "type 2 en_US", "locale" : "en_US" },
             "altDescriptions" : [{ "name" : "type 2 alt fr_FR", "locale" : "fr_FR" }]
           }
}
```

The query properly excludes 'child type 3' since it has no `en_US` description.  However, I'm not quite sure how to get it to exclude the `fr_FR` `altDescriptions `from the child type 1/2 results.  The results are otherwise what I want.

Can you please enlighten me?

1 Ответ

2 голосов
/ 29 февраля 2020

Вы можете использовать $ addFields для замены существующего массива и $ filter для применения вашего условия:

{
    $addFields: {
        "type.altDescriptions": {
            $filter: {
                input: "$type.altDescriptions",
                cond: {
                    $eq: [ "$$this.locale", "$type.description.locale" ]
                }
            }
        }
    }
}

Пн go Детская площадка

...