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

时间:2018-10-10 23:53:04

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

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

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}

在外壳中,它将类似于:

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

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

非常感谢您。

----编辑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 个答案:

答案 0 :(得分: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();