Java 如何按两个字段分组查找最新文档

Java 如何按两个字段分组查找最新文档,java,mongodb,nosql,Java,Mongodb,Nosql,我想得到每个地址和国家的最新文件。所以在下面的例子中,因为文档1和文档2具有相同的地址和国家,所以我选择了较新的一个-带有human1的文档,第三个文档是唯一的。因此,结果应该是两个文档,一个包含human1,另一个包含human3 { "human": "human1", "address": "address" "country": "country1" &

我想得到每个地址和国家的最新文件。所以在下面的例子中,因为文档1和文档2具有相同的地址和国家,所以我选择了较新的一个-带有human1的文档,第三个文档是唯一的。因此,结果应该是两个文档,一个包含human1,另一个包含human3

{
  "human": "human1",
  "address": "address"
  "country": "country1"
  "timestamp" : ISODate("2020-11-08T21:16:20.028Z"),
},
{
  "human": "human2",
  "address": "address"
  "country": "country1"
  "timestamp" : ISODate("2020-10-08T21:16:20.028Z"),
},
{
  "human": "human3",
  "address": "address"
  "country": "country2"
  "timestamp" : ISODate("2020-11-08T21:16:20.028Z"),
}
我的代码如下:

public start(){
List<Bson> collect = mongoCurrentAddress
                            .findByHuman(human.getName())
                            .stream().map(this::findCurrentHuman
                            ).filter(Objects::nonNull)
                            .collect(Collectors.toList());
Bson main = or(collect);
List<Human> humans= humanRepository.filter(main);
}

public Bson findCurrentHuman(Case case
    ) {
        return (match(and(
                regex("address", case.getAddress(),eq("country",case.getCountry())),
        limit(1),
                sort(Sorts.descending("timestamp", TIMESTAMP)));
    }

提前感谢您的任何提示

如果使用mongo模板和聚合,您可以轻松实现

  • $sort
    帮助使用时间戳执行描述顺序
  • $group
    $first
    有助于获取第一个对象
  • $replaceRoot
    有助于将文档重新设置为root
所需的mongo查询是

db.collection.aggregate([
  {
    $sort: {
      timestamp: -1
    }
  },
  {
    $group: {
      _id: {
        _id: "$address",
        country: "$country"
      },
      data: {
        $first: "$$ROOT"
      }
    }
  },
  {
    "$replaceRoot": {
      "newRoot": "$data"
    }
  }
])
工作

您需要自动连接Mongo模板

@Autowired
MongoTemplate mongoTemplate;
您需要的聚合是

public List<Object> test(){
    Aggregation aggregation = Aggregation.newAggregation(
        
        sort(Direction.DESC, "timestamp") ,
        group(  
            Fields.from(
                Fields.field("address", "$address"),
                Fields.field("country", "$country")
        ))
        .first("$$ROOT").as("data"),
         replaceRoot("data")    
        

    ).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());

    return mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(YOUR_COLLECTION.class), Object.class).getMappedResults();
} 
公共列表测试(){
Aggregation=Aggregation.newAggregation(
排序(Direction.DESC,“timestamp”),
集团(
字段(
字段。字段(“地址”,“美元地址”),
字段。字段(“国家”,“美元国家”)
))
.first($$ROOT”)。作为(“数据”),
replaceRoot(“数据”)
).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE.build());
返回mongoTemplate.aggregate(聚合,mongoTemplate.getCollectionName(您的_COLLECTION.class),Object.class).getMappedResults();
} 

注意:我还没有尝试上面的java代码。希望它能起作用。

嘿,非常感谢你的回答!!!!-但是现在我还没有找到一种在JavaEE上使用MongoTemplate的方法——这是我必须使用的方法,很抱歉我之前没有这么说,再一次谢谢!
public List<Object> test(){
    Aggregation aggregation = Aggregation.newAggregation(
        
        sort(Direction.DESC, "timestamp") ,
        group(  
            Fields.from(
                Fields.field("address", "$address"),
                Fields.field("country", "$country")
        ))
        .first("$$ROOT").as("data"),
         replaceRoot("data")    
        

    ).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());

    return mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(YOUR_COLLECTION.class), Object.class).getMappedResults();
}