使用 Mongodb 在 Spring 中截断和计算位置

Posted

技术标签:

【中文标题】使用 Mongodb 在 Spring 中截断和计算位置【英文标题】:Truncate and count positions in Spring with Mongodb 【发布时间】:2019-03-15 23:00:10 【问题描述】:

在我的应用程序中,我想显示一个热图,所以我需要这样的东西来构建它:

data: [lat: 24.6408, lng:46.7728, count: 3,lat: 50.75, lng:-1.55, count: 1, ...]

我有:

@Document(collection = "positions")
public class Position 
    @Id
    private String id;
    private long timestamp;
    @GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
    private GeoJsonPoint location;
    private File file;

为了对真正靠近的位置进行计数和分组,我考虑将所有位置截断,然后将它们分组进行计数。所以,例如:

"type" : "Point", "coordinates": [-47.121311,-18.151512]
"type" : "Point", "coordinates": [-47.121312,-18.151523]
"type" : "Point", "coordinates": [-47.121322,-18.151533]

结果:"type" : "Point, "coordinates" : [-47.1213,-18.1515], "count" : 3

在shell中它会是这样的:

"$map": 
          "input": '$location.coordinates',
          "in": 
            "$divide": [
               "$trunc":  "$multiply": [ '$$this', 10000 ]  ,
              10000
            ]                
          

然后我会按location.coordinates 分组。但我不知道这是否是正确的方法,也不知道在我的 PositionRepositoryCustom 中的 Spring 中编写此代码。我必须创建一个聚合,“绘制地图”,然后计算组。

非常感谢。

----编辑2---: 我创建了一个名为:

public class PositionSummary 

    private List<Double> coordinates;
    private Double count;

    public PositionSummary()  

    public List<Double> getCoordinates() 
        return coordinates;
    

    public void setCoordinates(List<Double> coordinates) 
        this.coordinates = coordinates;
    

    public Double getCount() 
        return count;
    

    public void setCount(Double count) 
        this.count = count;
    

而我的 CORRECTED 函数 AggregatePositions() 是:

@Override
public List<PositionSummary> AggregatePositionss() 

    AggregationOperation project =

            Aggregation.project("location")
                    .and( VariableOperators.mapItemsOf("location.coordinates").
                                    as("coord").
                                    andApply(
                                            ArithmeticOperators.valueOf(
                                                    ArithmeticOperators.valueOf(
                                                            ArithmeticOperators.valueOf(
                                                                    "$$coord"
                                                            ).multiplyBy(1000)
                                                    ).trunc()
                                            ).divideBy(1000)
                                    ))
                                    .as("coordinates");

    AggregationOperation group =
            Aggregation.group("coordinates")
                    .count().as("count");

    Aggregation agg = Aggregation.newAggregation(project,group);

    //AggregationResults<PositionSummary> groupResults = mongoTemplate.aggregate(agg, Position.class, PositionSummary.class);

    AggregationResults<PositionSummary> groupResults = mongoTemplate.aggregate(agg, "positions", PositionSummary.class);

    List<PositionSummary> result = groupResults.getMappedResults();


    return result;

我得到:

[
    
        "coordinates": null,
        "count": 1
    ,
    
        "coordinates": null,
        "count": 1
    ,
    
        "coordinates": null,
        "count": 2
    ,
    
        "coordinates": null,
        "count": 1
    ,
    
        "coordinates": null,
        "count": 2
    ,
...]

再次感谢您。

【问题讨论】:

【参考方案1】:

你的方法很好。使用以下聚合代码。

AggregationOperation project1 = 
         Aggregation.project("type")        
             .and(
                VariableOperators.mapItemsOf("location.coordinates").
                   as("coord").
                   andApply(
                    ArithmeticOperators.valueOf(
                      ArithmeticOperators.valueOf(         
                        ArithmeticOperators.valueOf(
                          "$$coord"
                        ).multiplyBy(1000)
                      ).trunc()
                    ).divideBy(1000)
                  )
             .as("coordinates");

AggregationOperation group = 
         Aggregation.group("coordinates")   
            .first("type").as("type")   
            .count().as("count");

AggregationOperation project2 = Aggregation.project("count","type").andExclude("_id").andInclude(Fields.from(Fields.field("coordinates", "_id")));

Aggregation agg = Aggregation.newAggregation(project1,group,project2);

List<Document> results = mongoTemplate.aggregate(agg,"positions",Document.class).getMappedResults();

【讨论】:

感谢您的回复,感谢您抽出宝贵时间。我用我所做的更新了我的答案,如果可以请检查一下,谢谢。 不客气。你能试试AggregationResults&lt;PositionSummary&gt; groupResults = mongoTemplate.aggregate(agg, "positions", PositionSummary.class);变种吗? 我按照你说的做了改变,但现在我得到了空坐标。我又更新了!谢谢 不客气。这是意料之中的。更新了答案以包括项目阶段。 我添加了新的项目阶段,现在确实可以使用了,非常感谢 Veeram!我觉得这个主题很困难,而且我没有找到很多示例和文档,因此非常感谢您的帮助。

以上是关于使用 Mongodb 在 Spring 中截断和计算位置的主要内容,如果未能解决你的问题,请参考以下文章

Mongodb 经常被截断

MongoDB Sink 连接器:Apache Kafka 中的消息被截断

如何使用Spring JdbcTemplate截断表?

使用 Spring 的 @Value 注释插入时如何避免截断前导零数字?

字符串数据,右截断 - 使用 Spring Boot 进行休眠

Spring 数据和 mongodb - 在 @Transactional 中使用 spring 进行简单回滚