Фильтрация результата запроса mongodb на основе позиции поля в массиве - PullRequest
1 голос
/ 16 февраля 2020

Извиняюсь за запутанный заголовок, я не уверен, как это обобщить.

Предположим, у меня есть следующий список документов в коллекции:

{ "name": "Lorem", "source": "A" }
{ "name": "Lorem", "source": "B" }
{ "name": "Ipsum", "source": "A" }
{ "name": "Ipsum", "source": "B" }
{ "name": "Ipsum", "source": "C" }
{ "name": "Foo",   "source": "B" }

, а также упорядоченный список из принятых источников, где более низкие индексы означают более высокий приоритет

sources = ["A", "B"]

Мой запрос должен:

  • Взять список доступных источников и список требуемых имен
  • Возвращать не более одного документа на имя.
  • В случае нескольких совпадений должен быть выбран документ с наиболее приоритетным источником.

Пример:

wanted_names = ['Lorem', 'Ipsum', 'Foo', 'NotThere']

Результат:

{ "name": "Lorem", "source": "A" }
{ "name": "Ipsum", "source": "A" }
{ "name": "Foo",   "source": "B" }

Результаты не обязательно должны быть упорядочены.

Возможно ли это сделать только с помощью запроса Mon go? Если так, то может ли кто-нибудь указать мне на ресурс, подробно описывающий, как выполнить sh it?

Мое текущее решение не поддерживает список имен, а вместо этого использует сценарий Python для выполнения нескольких запросов:

db.collection.aggregate([
    {$match: {
        "name": "Lorem",
        "source": {
            $in: sources
    }}},
    {$addFields: {
        "order": {
            $indexOfArray: [sources, "$source"]
    }}},
    {$sort: {
        "order": 1
    }},
    {$limit: 1}
]);

Примечание: _id поля опущены в этом вопросе для краткости

1 Ответ

1 голос
/ 16 февраля 2020

Как насчет этого: С $group у нас есть $min оператор, который принимает нижний источник

Примечание: Если вы расставите приоритеты как ['B', «A»], используйте $max, затем

db.collection.aggregate([
  {
    $match: {
      "name": {
        $in: [
          "Lorem",
          "Ipsum",
          "Foo",
          "NotThere"
        ]
      },
      "source": {
        $in: [
          "A",
          "B"
        ]
      }
    }
  },
  {
    $group: {
      _id: "$name",
      source: {
        $min: "$source"
      }
    }
  },
  {
    $project: {
      _id: 0,
      name: "$_id",
      source: 1
    }
  }
])

MongoPlayground

...