在没有双向参考的情况下找到元素的最高祖先

时间:2019-01-31 12:59:59

标签: mongodb spring-data spring-data-mongodb

我正在使用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
    ]
}

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

我更喜欢使用Spring Data Repository的智能方法命名的惰性方式,类似Category findBySubCategoriesItems(Item item),但@Query也很受赞赏!

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

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

我尝试进行另一种处理,获取顶级类别并按以下项进行过滤:category.*.items.id : someItemId,但不幸的是,不支持通配符“任何深度”查询,如{{3 }}

编辑2:我一直在阅读有关GraphLookup的信息,但据我了解,只有设置了父级关系时,它才能找到根类别,而仅设置了子级时,它就不能使用它。

1 个答案:

答案 0 :(得分:2)

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