Mongo DB按日期排序并按标签分组

洛伦佐·波利多里(Lorenzo Polidori)

我有一个类似于以下内容的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", "green", "blue"],则应得到类似于以下结果:

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

我的问题是:

  1. 获得以上结果的最佳Mongo DB查询是什么?
  2. 如果周围有任何熟练的Spring Data专家,那么如何将其转换为Spring Data查询,可能使用AggregationOperation

我对问题1的回答很满意,我可以分别寻找问题2的答案。

当然

如前所述,您可以通过聚合来实现

  1. $sort创建由下降到订单
  2. $facet有助于对我们$match用来过滤标签的内部文档进行分类
  3. $project有助于投影。我们已经按创建了排序因此,我们将通过获取第一个元素$arrayElemAt,有时,如果没有元素,它将引发异常,因此,为了返回空对象,我们使用$ifNull

Mongo脚本

[
  {
    $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();

}

注意:我没有在spring-boot中测试以上代码。但是它是基于有效的mongo脚本编写的。希望它能工作。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章