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

5w9g7ksd  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(510)

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

{
  "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)));
    }

对我来说唯一有效的方法就是为每个案例创建一个单独的查询(尽可能多的地址和国家,尽可能多的查询最新的文档)。
在上述情况下,我得到错误:

com.mongodb.MongoCommandException: Command failed with error 2 (BadValue): 'unknown top level operator: $ limit' on server localhost.localdomain: 27017. The full response is {"ok": 0.0, "errmsg": "unknown top level operator: $ limit", "code": 2, "codeName": "BadValue", "operationTime": {"$ timestamp": { "t": 1605438274, "i": 1}}, "$ clusterTime": {"clusterTime": {"$ timestamp": {"t": 1605438274, "i": 1}}, "signature": { "hash": {"$ binary": "W28RhgZ7dgzxcxzcwr0LvNO1QBUuOTU =", "$ type": "00"}, "keyId": {"$ numberLong": "689282134513089875974"}}}}

提前谢谢你的提示!

hc8w905p

hc8w905p1#

如果您使用mongo模板和聚合,您可以轻松实现 $sort 帮助使用时间戳执行描述顺序 $group 以及 $first 有助于获取第一个对象 $replaceRoot 有助于使文档再次成为根目录
所需的mongo查询是

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

工作蒙哥Playground
你需要自动连接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();
}

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

相关问题