Ask Your Question
4

How can the sum of distances be calculated in a mongodb/java springboot query that sorts user lists based on their distance from a logged-in user?

asked 2021-12-05 11:00:00 +0000

qstack gravatar image

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
1

answered 2021-12-04 13:00:00 +0000

lakamha gravatar image

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.

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account. This space is reserved only for answers. If you would like to engage in a discussion, please instead post a comment under the question or an answer that you would like to discuss

Add Answer


Question Tools

Stats

Asked: 2021-12-05 11:00:00 +0000

Seen: 12 times

Last updated: Dec 04 '21