Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

To calculate the sum of distances, you can use the $geoNear aggregation pipeline operator in MongoDB, which allows you to calculate the distance between two points on a sphere using the Haversine formula. Here's an example query that sorts user lists based on their distance from a logged-in user and returns the sum of distances for each user:

db.users.aggregate([
  {
    $geoNear: {
      near: { type: "Point", coordinates: [longitude, latitude] },
      distanceField: "distance",
      spherical: true
    }
  },
  {
    $group: {
      _id: "$_id",
      username: { $first: "$username" },
      distanceSum: { $sum: "$distance" }
    }
  },
  {
    $sort: { distanceSum: 1 }
  }
])

This query first uses $geoNear to get the distance between the point specified by longitude and latitude and each user's coordinates. The distance is stored in the "distance" field for each document. It then groups the documents by the user's _id and username, and calculates the sum of distances for each user using $sum. Finally, it sorts the result by distanceSum in ascending order.

In Java Spring Boot, you can use the MongoTemplate class to execute this query. Here's an example method that returns a list of User objects sorted by their distance from a given point:

public List<User> getUsersSortedByDistance(double longitude, double latitude) {
  MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory);
  Aggregation agg = Aggregation.newAggregation(
    Aggregation.geoNear("users")
      .near(new Point(longitude, latitude))
      .distanceField("distance")
      .spherical(true),
    Aggregation.group("_id", "username")
      .first("$_id").as("id")
      .first("$username").as("username")
      .sum("distance").as("distanceSum"),
    Aggregation.sort(Sort.Direction.ASC, "distanceSum")
  );
  AggregationResults<BasicDBObject> results = mongoTemplate.aggregate(agg, "users", BasicDBObject.class);
  List<User> users = new ArrayList<>();
  for (BasicDBObject result : results) {
    User user = new User();
    user.setId(result.getInteger("id"));
    user.setUsername(result.getString("username"));
    user.setDistanceSum(result.getDouble("distanceSum"));
    users.add(user);
  }
  return users;
}

This method uses the Aggregation class to define the aggregation pipeline and the MongoTemplate class to execute the query. It returns a list of User objects sorted by their distanceSum property. Note that you'll need to inject the MongoDbFactory instance into your Spring Boot application context in order to use the MongoTemplate class.