MongoDB - findOne с вложенными вложенными документами и проекцией - PullRequest
0 голосов
/ 17 июня 2020

В настоящее время я использую приведенный ниже код в node.js, чтобы найти и вернуть данные на различных уровнях вложенности из базы данных mon go. Я хотел бы добавить еще один уровень вложенности (как упоминалось в №3).

Коллекция:

[
  {
    "title": "Category A",
    "link": "a",
    "items": [
      {
        "title": "Item C",
        "link": "a-c",
        "series": [
          {
            "title": "Item C X",
            "link": "a-c-x"
          },
          {
            "title": "Item C Y",
            "link": "a-c-y"
          },

        ]
      },
      {
        "title": "Item D",
        "link": "a-d"
      }
    ]
  },
  {
    "title": "Category B",
    "link": "b"
  }
]

Запрос:

const doc = await ... .findOne(
    {
        $or: [
            { link: id },
            { "items.link": id },
            { "items.series.link": id }
        ],
    },
    {
        projection: {
            _id: 0,
            title: 1,
            link: 1,
            items: { $elemMatch: { link: id } },
        },
    }
);

Предполагаемые результаты:

  1. (работает), если совпадает link документа,
    (работает), должен быть только объект с возвращенным заголовком и ссылкой
    например,
    значение переменной id: "a"
    ожидаемый результат запроса: { title: "Category A", link: "a"}

  2. (работает), если совпадает items.link вложенного документа,
    (работает) должно быть таким же, как указано выше + дополнительный элемент в возвращаемом массиве элементов.
    например,
    значение переменной id: "a-c"
    ожидаемый результат запроса: { title: "Category A", link: "a", items: [{ title: "Item C", link: "a-c" }]}

  3. (работает), если совпадает items.series.link вложенного документа
    (борется с этим) он должен возвращать то же, что и в 2. + дополнительный элемент внутри сопоставленного items.series
    например,
    значение переменной id : "a-c-y"
    ожидаемый результат запроса : { title: "Category A", link: "a", items: [{ title: "Item C", link: "a-c", series: [{ title: "Item C Y", link: "a-c-y" }]}]}
    текущий результат запроса : весь Документ категории А со всеми дополнительными документами

Вопросы:

a.) Как мне изменить проекцию, чтобы вернуть ожидаемый результат в # 3?

б.) Является ли подход, описанный выше, приемлемым с точки зрения скорости чтения денормализованной структуры? Я подумал, что, вероятно, потребуются индексы для ссылок, items.link и items.series.link, поскольку все они полностью уникальны в документе, но, может быть, есть способ достичь указанной выше цели с помощью совершенно другого подхода?

1 Ответ

0 голосов
/ 21 июня 2020

Закончился переходом на полпути через mongodb и получением полного элемента для обоих - когда сопоставлена ​​ссылка на элемент и сопоставлена ​​ссылка на серию:

projection: {
  _id: 0,
  title: 1,
  link: 1,
  items: { $elemMatch: { $or: [
    { link: id },
    {"series.link": id }
  ]}},
}

После этого javascript фильтрует серию массив, чтобы увидеть, совпадает ли серия:

doc?.items?.[0]?.series?.find(item => item.link === id)

если js истинно (возвращает объект), мы сопоставили серию, если есть do c, но js - ложь, мы сопоставили результат элемента.

Хотя это не полное решение mongodb и определенно есть возможности для улучшения, вышеупомянутое, похоже, достигает конечной цели - иметь возможность различать guish между категорией, элементом и результаты серии.

...