根据条件删除重复项

时间:2020-01-10 12:07:14

标签: java mongodb aggregation-framework spring-data-mongodb

我在下面的列表中有重复的元素

我要根据版本和日期属性从列表中删除所有重复项

这意味着,如果有重复的元素,我得到的是具有状态actif的元素,如果没有人有状态的actif,那么我可以获得具有最近日期的那个

[
   {
      "_id" : ObjectId("5e1832df02f04352705457dd"),
      "product":"1",
      "version":{
         "state":"Actif",
         "name":"1.0.0"
      },
      "createdDate":"01/01/2020"
   },
   {
      "_id" : ObjectId("5e1832df02f04352705457ff"),
      "product":"1",
      "version":{
         "state":"A faire",
         "name":"3.0.0"
      },
      "createdDate":"01/01/2020"
   },
   {
      "_id" : ObjectId("5e1832df02f04352705457ee"),
      "product":"1",
      "version":{
         "state":"Archiver",
         "name":"2.0.0"
      },
      "createdDate":"02/01/2020"
   },
   {
      "_id" : ObjectId("5e1832df02f04352705457gg"),
      "product":"2",
      "version":null,
      "createdDate":"01/01/2020"
   },
   {
      "_id" : ObjectId("5e1832df02f04352705457yy"),
      "product":"2",
      "version":{
         "state":"Archiver",
         "name":"2.0.0"
      },
      "createdDate":"02/01/2020"
   },
   {
      "_id" : ObjectId("5e1832df02f04352705455ss"),
      "product":"3",
      "version":{
         "state":"Archiver",
         "name":"2.0.0"
      },
      "createdDate":"01/01/2020"
   }
]

输出应如下所示:

[
   {
      "_id" : ObjectId("5e1832df02f04352705457dd"),
      "product":"1",
      "version":{
         "state":"Actif",
         "name":"1.0.0"
      },
      "createdDate":"01/01/2020"
   },
   {
      "_id" : ObjectId("5e1832df02f04352705457yy"),
      "product":"2",
      "version":{
         "state":"Archiver",
         "name":"2.0.0"
      },
      "createdDate":"02/01/2020"
   },
   {
      "_id" : ObjectId("5e1832df02f04352705455ss"),
      "product":"3",
      "version":{
         "state":"Archiver",
         "name":"2.0.0"
      },
      "createdDate":"01/01/2020"
   }
]

public List<Product> search() {
    final Query query = new Query().with(new Sort(new Order(Direction.DESC, "createdDate")));
    return mongoOperations.find(query, Product.class);
}

我们如何做到这一点?

2 个答案:

答案 0 :(得分:0)

您需要使用aggregate方法。

Java代码

未经测试! 如果AggregationOperation希望实现toDocument方法,请将所有BasicDBObject更改为Document

import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;

Aggregation aggregation = newAggregation(
        sort(Sort.Direction.ASC, "product", "version", "createdDate"), 
        group("product").last("$$ROOT").as("root"),
        sort(Sort.Direction.ASC, "_id"),
        //$replaceRoot
        );

return mongoTemplate.aggregate(aggregation, Product.class, Product.class).getMappedResults();

MongoDB shell

db.Product.aggregate([
  {
    $sort: {
      product: 1,
      version: -1,
      createdDate: -1
    }
  },
  {
    $group: {
      _id: "$product",
      root: {
        $push: "$$ROOT"
      }
    }
  },
  {
    $sort: {
      _id: 1
    }
  },
  {
    $replaceRoot: {
      newRoot: {
        $arrayElemAt: [
          {
            $concatArrays: [
              {
                $filter: {
                  input: "$root",
                  cond: {
                    $eq: [
                      "$$this.version.state",
                      "Actif"
                    ]
                  }
                }
              },
              [
                {
                  $arrayElemAt: [
                    "$root",
                    0
                  ]
                }
              ]
            ]
          },
          0
        ]
      }
    }
  }
])

MongoPlayground

答案 1 :(得分:0)

使用Spring Data 2.2和MongoDB 3.4兼容的聚合运算符进行聚合。

MongoOperations mongoOps = new MongoTemplate(MongoClients.create(), "spr_test");

Aggregation agg = newAggregation(
    project("product", "version")
        .and(Concat.valueOf(SubstrCP.valueOf("createdDate").substringCP(6, 4))
                .concat("-")
                .concatValueOf(SubstrCP.valueOf("createdDate").substringCP(3, 2))
                .concat("-")
                .concatValueOf(SubstrCP.valueOf("createdDate").substringCP(0, 2)) )
        .as("createdDate"),
    group("product")
        .push("$$ROOT").as("details")
        .push("createdDate").as("createdDates"),
    facet(   
        project("details")
            .and(Size.lengthOfArray("details")).as("arrSize"),
        match(where("arrSize").is(new Integer(1))))
    .as("c1")
    .and(
        match(where("details.version.state").is("Actif" )), 
        project()
            .and(filter("details")
                .as("d")
                .by(Eq.valueOf("d.version.state").equalToValue("Actif" )))
            .as("details"))
    .as("c2")
    .and(
        project("details", "createdDates")
            .and(Size.lengthOfArray("details")).as("arrSize"),
        match(where("arrSize").gt(new Integer(1))
            .and("details.version.state").ne("Actif")),
        project()
            .and(filter("details")
                .as("d")
                .by(Eq.valueOf("d.createdDate").equalTo(Max.maxOf("createdDates"))))
            .as("details"))
    .as("c3"),
    project()
        .and(arrayOf("c1").concat("c2").concat("c3"))
        .as("result"),
    unwind("result"),
    project()
        .and(arrayOf("result.details").elementAt(0)).as("result")
);

AggregationResults<Document> results = mongoOps.aggregate(agg, "test", Document.class);

results.forEach(System.out::println);