在没有双向引用的情况下查找元素的最高级别祖先

Find an element's highest level ancestor without having bi-directional reference

我正在使用 MongoDB 在类别中存储子类别,在子类别中存储项目。我想按项目检索主要类别。在没有双向参考的情况下,如何以最简单的方式在 Spring 数据中做到这一点?

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
    ]
}

我想通过子类别 2 提供 itemID 001(这是 Items 集合中的一个项目)来找到 ID 为 1 的类别,不假设连接深度

我更喜欢 Spring Data Repository 的智能方法命名的懒惰方式,类似于 Category findBySubCategoriesItems(Item item)@Query 也非常受欢迎!

编辑:我可以通过 itemId 从 MongoDB 控制台找到子类别,但我不知道如何递归地进入根类别。这是我的查询:

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

我尝试反过来,获取顶级类别并按如下项目过滤:category.*.items.id : someItemId 但不幸的是不支持通配符 "any depth" 查询,如中所述https://jira.mongodb.org/browse/SERVER-267

编辑 2:我一直在阅读有关 GraphLookup 的内容,但据我了解,如果设置了父关系,它只能找到根类别,而当仅设置子关系时无法使用它进行操作。

Graphlookup 绝对是正确的选择, 假设两个集合名称分别是'items'和'categories',

  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"
              }
            ]
          }
        }
      }
    }
  }
])