首页 > 解决方案 > MongoTemplate 按嵌套列表中的字段搜索

问题描述

我有一个像下面这样list的对象MainItem

[
   {
      "_id":"5ee40defc4b47b54a223120f",
      "name":"Item 1",
      "subItems":[
         {
            "_id":"111",
            "name":"cat One name",
            "description":"cat item description"
         },
         {
            "_id":"222",
            "name":"cat Two name",
            "description":"cat item description"
         }
      ]
   },
   {
      "_id":"5ee40defc4b47b54a223120f",
      "name":"Item 1",
      "subItems":[
         {
            "_id":"333",
            "name":"cat Three name",
            "description":"cat item description"
         },
         {
            "_id":"222",
            "name":"cat Two name",
            "description":"cat item description"
         }
      ]
   },
   {
      "_id":"5ee40defc4b47b54a223120f",
      "name":"Item 1",
      "subItems":[
         {
            "_id":"333",
            "name":"cat Three name",
            "description":"cat item description"
         },
         {
            "_id":"111",
            "name":"cat One name",
            "description":"cat item description"
         }
      ]
   }
]

我想做的是按subItem名称搜索。因此,如果像“cat Th”这样搜索,我的结果应该如下所示(应该返回SubItem与名称匹配的列表列表),

[
    {
        "_id":"333",
        "name":"cat Three name",
        "description":"cat item description"
    }
]

我需要通过使用 mongoTemplate 来做到这一点,这是我用来获得结果的那个,

mongoTemplate.getCollection(mongoTemplate.getCollectionName(MainItem.class)).distinct("subItems", new BasicDBObject("subItems.name", new BasicDBObject("$regex", "^cat Th")), BasicBSONObject.class).into(new ArrayList<>())

我没有在列表中获取匹配的子项,而是得到了所有不同的子项,我在这里做错了什么?

(相同的 SubItem 可以在不同的 MainItem 列表中,在这些情况下,应该有不同的 SubItems 匹配名称)

标签: mongodbmongodb-queryaggregation-frameworkmongotemplate

解决方案


在对聚合框架进行一些研究并在 MongoTemplate 中使用聚合方法之后,我想出了这个解决方案来解决我的问题。

final UnwindOperation unwind = unwind("subItems");
final GroupOperation group = Aggregation.group("subItems");
final ReplaceRootOperation replaceRoot = replaceRoot("_id");
final MatchOperation matchName = match(Criteria.where("name").regex("^" + name, "i"));
final Aggregation aggregation = newAggregation(unwind, group, replaceRoot, matchName);

mongoTemplate
  .aggregate(aggregation, mongoTemplate.getCollectionName(MenuItem.class), SubItem.class)
  .getMappedResults();

推荐阅读