Найти предка самого высокого уровня элемента, не имея двунаправленной ссылки - PullRequest
0 голосов
/ 31 января 2019

Я использую MongoDB для хранения подкатегорий в категориях и элементов в подкатегориях.Я хотел бы получить основную категорию по элементу.Как я могу сделать это в Spring Data самым простым способом без двунаправленной ссылки?

class Category {    
    private String id;

    //some other attributes

    @DbRef
    List<Category> subCategories = new ArrayList<>();

    @DbRef
    List<Item> items = new ArrayList<>();
}

В БД коллекция категорий выглядит примерно так:

{
    id: 1,
    subcategories: [
        2, 3   
    ]
},
{
    id: 2,
    items: [
        001
    ]
}

Я бынравится находить категорию с идентификатором 1, предоставляя itemID 001 (который является элементом в коллекции Items), через подкатегорию 2, без учета глубины соединений .

Я бы предпочел ленивый способ с умным именованием методов Spring Data Repository, что-то вроде Category findBySubCategoriesItems(Item item), но @Query также очень ценится!

Редактировать: я могу найти подкатегорию из MongoDBконсоль по itemId, но я не знаю, как рекурсивно перейти к корневой категории.Это мой запрос:

db.category.find({ items: { id: ObjectId("someItemId") } })

Я пытался пойти по другому пути, получить категории верхнего уровня и выполнить фильтрацию по элементу, например так: category.*.items.id : someItemId но, к сожалению, подстановочный знак «любая глубина» не соответствуетподдерживается, как указано в https://jira.mongodb.org/browse/SERVER-267

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

1 Ответ

0 голосов
/ 07 февраля 2019

Graphlookup - это определенно правильный путь, если предположить, что имена двух коллекций - «items» и «category»,

  db.items.aggregate([
  {
    // find the item in items collection
    $match: {
      items: '001'
    },

  },
  // recursively find the categories starting from matched item
  {
    $graphLookup: {
      from: "categories",
      startWith: "$id",
      connectFromField: "id",
      connectToField: "subcategories",
      as: "categories",
      depthField: "level"
    }
  },
  // get only the root node (this is optional, basically if you skip the below stage, you'll get the entire recursive category list along with the matched item)
  {
    $project: {
      root_category: {
        $filter: {
          input: "$categories",
          as: "category",
          cond: {
            $eq: [
              "$$category.level",
              {
                $max: "$categories.level"
              }
            ]
          }
        }
      }
    }
  }
])
...