Mongodb Mongo DB按日期排序和按标记分组

Mongodb Mongo DB按日期排序和按标记分组,mongodb,jpa,spring-data-jpa,mongodb-query,Mongodb,Jpa,Spring Data Jpa,Mongodb Query,我有一个类似以下内容的Mongo DB集合: { "_id": "...", "name": "name 1", "created": "2020-07-21T08:11:18.414+00:00", "tags": ["red", "green"] } { "_id&

我有一个类似以下内容的Mongo DB集合:

{
    "_id": "...",
    "name": "name 1",
    "created": "2020-07-21T08:11:18.414+00:00",
    "tags": ["red", "green"]
}
{
    "_id": "...",
    "name": "name 2",
    "created": "2020-07-20T08:11:18.414+00:00",
    "tags": ["red", "blue"]
}
{
    "_id": "...",
    "name": "name 3",
    "created": "2020-07-19T08:11:18.414+00:00",
    "tags": ["green", "blue"]
}
{
    "_id": "...",
    "name": "name 4",
    "created": "2020-07-18T08:11:18.414+00:00",
    "tags": ["white", "blue"]
}
{
    "_id": "...",
    "name": "name 5",
    "created": "2020-07-17T08:11:18.414+00:00",
    "tags": ["white", "green"]
}
{
    "red": {
        "_id": "...",
        "name": "name 1",
        "created": "2020-07-21T08:11:18.414+00:00",
        "tags": ["red", "green"]
    },
    "green": {
        "_id": "...",
        "name": "name 1",
        "created": "2020-07-21T08:11:18.414+00:00",
        "tags": ["red", "green"]
    },
    "blue": {
        "_id": "...",
        "name": "name 2",
        "created": "2020-07-20T08:11:18.414+00:00",
        "tags": ["red", "blue"]
    }
}
我需要能够指定标记列表,并且对于列表中的每个标记,我需要获取最近创建的文档。在上面的示例中,如果我指定
[“红色”、“绿色”、“蓝色”]
,我将得到类似的结果:

{
    "_id": "...",
    "name": "name 1",
    "created": "2020-07-21T08:11:18.414+00:00",
    "tags": ["red", "green"]
}
{
    "_id": "...",
    "name": "name 2",
    "created": "2020-07-20T08:11:18.414+00:00",
    "tags": ["red", "blue"]
}
{
    "_id": "...",
    "name": "name 3",
    "created": "2020-07-19T08:11:18.414+00:00",
    "tags": ["green", "blue"]
}
{
    "_id": "...",
    "name": "name 4",
    "created": "2020-07-18T08:11:18.414+00:00",
    "tags": ["white", "blue"]
}
{
    "_id": "...",
    "name": "name 5",
    "created": "2020-07-17T08:11:18.414+00:00",
    "tags": ["white", "green"]
}
{
    "red": {
        "_id": "...",
        "name": "name 1",
        "created": "2020-07-21T08:11:18.414+00:00",
        "tags": ["red", "green"]
    },
    "green": {
        "_id": "...",
        "name": "name 1",
        "created": "2020-07-21T08:11:18.414+00:00",
        "tags": ["red", "green"]
    },
    "blue": {
        "_id": "...",
        "name": "name 2",
        "created": "2020-07-20T08:11:18.414+00:00",
        "tags": ["red", "blue"]
    }
}
我的问题是:

  • 获得上述结果的最佳Mongo DB查询是什么
  • 如果有任何熟练的Spring数据专家在场,如何将其转换为Spring数据查询,可能使用
    聚合操作

  • 我很高兴能对问题1给出一个好的答案,我也可以单独寻找问题2的答案。

    正如您所提到的,您可以通过聚合来实现这一点

  • $sort
    按降序创建的
  • $facet
    帮助对内部文档进行分类,我们使用
    $match
    过滤标记
  • $project
    有助于投影。我们已经按创建的排序了。因此,我们将通过
    $arrayElemAt
    获取第一个元素,有时如果没有元素,它将抛出异常,因此为了返回空对象,我们使用
    $ifNull
  • 蒙哥文字

    [
      {
        $sort: {
          created: -1
        }
      },
      {
        $facet: {
          red: [
            {
              $match: {
                tags: "red"
              }
            }
          ],
          green: [
            {
              $match: {
                tags: "green"
              }
            }
          ],
          blue: [
            {
              $match: {
                tags: "blue"
              }
            }
          ]
        }
      },
      {
        $project: {
          red: {
            $ifNull: [
              {
                "$arrayElemAt": [
                  "$red",
                  0
                ]
              },
              {}
            ]
          },
          blue: {
            $ifNull: [
              {
                "$arrayElemAt": [
                  "$blue",
                  0
                ]
              },
              {}
            ]
          },
          green: {
            $ifNull: [
              {
                "$arrayElemAt": [
                  "$green",
                  0
                ]
              },
              {}
            ]
          }
        }
      }
    ]
    
    工作

    当我们将其转换为Spring数据时

    public List<Object> test() {
        Aggregation aggregation = Aggregation.newAggregation(
                sort(Sort.Direction.DESC, "created"),
                facet(
                        match(Criteria.where("tags").is("red"))
                ).as("red")
                        .and(
                                match(Criteria.where("tags").is("green"))
                        ).as("green")
                        .and(
                                match(Criteria.where("tags").is("blue"))
                        ).as("blue"),
                project()
                        .and(ConditionalOperators.ifNull(ArrayOperators.arrayOf("red").elementAt(0)).then(new Document())).as("red")
                        .and(ConditionalOperators.ifNull(ArrayOperators.arrayOf("blue").elementAt(0)).then(new Document())).as("blue")
                        .and(ConditionalOperators.ifNull(ArrayOperators.arrayOf("green").elementAt(0)).then(new Document())).as("green")
    
        ).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());
    
        return mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(YOUR_COLLECTION.class), Object.class).getMappedResults();
    
    }
    
    公共列表测试(){
    Aggregation=Aggregation.newAggregation(
    排序(sort.Direction.DESC,“已创建”),
    小平面(
    匹配(标准,其中“标签”为“红色”)
    ).as(“红色”)
    .及(
    匹配(标准,其中“标签”为“绿色”)
    ).as(“绿色”)
    .及(
    匹配(标准。其中(“标签”)为(“蓝色”))
    ).以“蓝色”命名,
    项目()
    和(ConditionalOperators.ifNull(ArrayOperators.arrayOf(“红色”).elementAt(0))。然后(new Document()).as(“红色”)
    和(ConditionalOperators.ifNull(ArrayOperators.arrayOf(“蓝色”).elementAt(0))。然后(new Document()).as(“蓝色”)
    和(ConditionalOperators.ifNull(ArrayOperators.arrayOf(“绿色”).elementAt(0))。然后(new Document()).as(“绿色”)
    ).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE.build());
    返回mongoTemplate.aggregate(聚合,mongoTemplate.getCollectionName(您的_COLLECTION.class),Object.class).getMappedResults();
    }
    

    注意:我还没有在spring boot中测试上述代码。但它是基于mongo脚本编写的。希望它能起作用。

    谢谢!我会测试一下,让你知道我也在找同样的。如果您成功使用此解决方案,请与我们分享。@varman测试成功(包括java代码),谢谢