$ lookup два уровня - PullRequest
       7

$ lookup два уровня

0 голосов
/ 27 января 2019

Я новичок в MongoDB и NoSQL, и я пытаюсь почувствовать (в течение довольно ограниченного периода времени), будет ли он работать для быстрого демонстрационного проекта, для которого у нас уже есть данные в виде файлов json. Я пытаюсь протестировать разные сценарии запросов с Mongo, и есть один сценарий, в котором я застрял. Представьте, что у меня есть 3 коллекции mongodb, представляющие продукты с категориями и подкатегориями. Каждый проект может иметь много категорий, и каждая категория может иметь много подкатегорий. Вот простой пример данных:

Продукты

{ "id" : "1", "name" : "product1", "categories": ["cat1_id", "cat2_id"] }
{ "id" : "2", "name" : "product2", "categories": ["cat1_id"]}
{ "id" : "3", "name" : "product3", "categories": ["cat3_id"}

Категория

{ "id" : "cat1_id", "name" : "cat1", "sub_categories": ["subcat1_id", "scat2_id"]}
{ "id" : "cat2_id", "name" : "cat2", "sub_categories": ["subcat3_id"]}
{ "id" : "cat3_id", "name" : "cat3", "sub_categories": ["subcat1_id"]}

Подкатегория

{ "id" : "subcat1_id", "name" : "sub cat1"}
{ "id" : "subcat2_id", "name" : "sub cat2"}
{ "id" : "subcat3_id", "name" : "sub cat3"}

Я пытаюсь найти 3 коллекции, чтобы получить данные по категориям и подкатегориям в документах по продукту:

{ 
  "id" : "1", 
  "name" : "product1", 
  "categories": [{
    "id": "cat1_id", 
    "name": "cat1", 
    "sub_categories": [
      { "id" : "subcat1_id", "name" : "sub cat1"}
      { "id" : "subcat2_id", "name" : "sub cat2"}
    ]
  }, {
    "id": "cat2_id", 
    "name": "cat2", 
    "sub_categories": [
      { "id" : "subcat1_id", "name" : "sub cat1"}
    ]
  }]
}

Я делаю 2 поиска и перепробовал несколько вариантов, но если у продукта есть 2 категории, я всегда получаю информацию о подкатегориях только для первой категории - детали для подкатегорий второй категории пропали и даже для категории 2 я получаю подкатегории категории 1.

Вот запрос и результат, который я получил:

Запрос

db.product.aggregate([
    $lookup: {
        from: "category",
        localField: "categories",
        foreignField: "id",
        as: "categories_obj"
    },
    $unwind: "categories",
    $unwind: "categories_obj.sub_categories",
    $lookup: {
        from: "sub_category",
        localField: "categories_obj.sub_categories",
        foreignField: "id",
        as: "sub_category_obj"
    }
])

Результат

{
  "id" : "1", 
  "name" : "product1",
  "categories": "cat1_id"
  "categories_obj" : [
     { "id" : "cat1_id", "name" : "cat1", "sub_categories": ["subcat1_id", 
     "scat2_id"]}
     { "id" : "cat2_id", "name" : "cat2", "sub_categories": ["subcat3_id"]}
  ],
  "sub_category_obj": [
     { "id" : "subcat1_id", "name" : "sub cat1"}
     { "id" : "subcat2_id", "name" : "sub cat2"}
  ]
}
{
  "id" : "1", 
  "name" : "product1",
  "categories": "cat2_id"
  "categories_obj" : [
     { "id" : "cat1_id", "name" : "cat1", "sub_categories": ["subcat1_id", 
     "scat2_id"]}
     { "id" : "cat2_id", "name" : "cat2", "sub_categories": ["subcat3_id"]}
  ],
  "sub_category_obj": [
     { "id" : "subcat1_id", "name" : "sub cat1"}
     { "id" : "subcat2_id", "name" : "sub cat2"}
  ]
}

Как видно из результата, и cat1, и cat2 отображают детали для подкатегорий 1 и 2 (принадлежит к cat1), но подкатегория 3 отсутствует (принадлежит к cat2). Как только я смогу получить детали для всех подкатегорий, я попытаюсь получить $ group, $ project и т.д., чтобы получить желаемый формат данных, описанный выше, но я не знаю, как получить все детали подкатегорий. ,

Пожалуйста, помогите мне с этим. Я надеюсь, что это возможно с MongoDB.
Также будет приветствоваться запрос для получения данных в описанном формате!
Спасибо!

1 Ответ

0 голосов
/ 27 января 2019

Вы можете использовать агрегацию ниже с mongodb 3.6 и выше

Project.aggregate([
  { "$lookup": {
    "from": Category.collection.name,
    "let": { "categories": "$categories" },
    "pipeline": [
      { "$match": { "$expr": { "$in": [ "$_id", "$$categories" ] } } },
      { "$lookup": {
        "from": SubCategory.collection.name,
        "let": { "sub_categories": "$sub_categories" },
        "pipeline": [
          { "$match": { "$expr": { "$in": [ "$_id", "$$sub_categories" ] } } }
        ],
        "as": "sub_categories"
      }}
    ],
    "as": "categories"
  }}
])
...