使用mongodb/java springboot通过登录用户和用户列表之间的距离进行排序的查询中的距离增加

kb5ga3dv  于 2023-04-04  发布在  Java
关注(0)|答案(1)|浏览(131)

bounty还有15小时到期,回答此问题可获得+150声望奖励,The Old County正在寻找规范答案:我正在使用getUserList API --并且我已经获得了当前功能来对集合中的普通字段进行排序--但是我希望能够使用登录用户的纬度/lng作为基础通过距离进行排序--以计算与其他用户的纬度/lng的距离---请查看简报的顶部,其中我列出了“@GetMapping”的当前控制器(“/API/users”)”

在switch的例子中,我希望能够通过距离对用户进行排序,我认为这意味着使用聚合来创建虚拟距离字段,我不确定如何集成它,我只知道一些制作聚合的方法,但是没有任何东西可以使用addCriteria Springboot方法添加到我的代码库中。
我正在一个Java/Mongodb系统上工作,在这个系统中,每个用户都有自己的lat/lng坐标
我已经对用户集合进行了一个API查询--我想开始对用户进行过滤/排序。
我想完成这个排序过程--它对选项2-5很好--但是我需要弄清楚如何在mongo中创建一个聚合(我是新手)。
一个用户记录看起来像这样--我把坐标放在locations对象中,其他过滤器大多在根目录中--比如createdAt,lastLoginAt...

如何开始使用当前代码库创建所需的聚合--这样我就可以对登录的用户进行排序--获取他们的坐标--并对查看列表中的用户进行排序。
使用springframework导入

import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
@CrossOrigin
@GetMapping("/api/users")
@ResponseBody
public BasicDBObject listUsers (@RequestHeader("Authorization") String bearerToken, @RequestParam("sort_by") String sort_by, @RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "3") int size) {

    String email = tokenHandler.getEmailFromBearerToken(bearerToken);

    //get logged in user
    Query q = new Query();
    q.addCriteria(Criteria.where("email").is(email));
    List<Person> lp = MongoApp.mongoOps().find(q, Person.class);
    Person loggedInUser = null;
    if (!lp.isEmpty()) {
        for (Person person : lp) {
            loggedInUser = person;
        }
    }

    String field = "";//createdAt
    switch (sort_by) {
        case "1":
            System.out.println("Distance");
            break;
        case "2":
            System.out.println("Last online");
            field = "lastLoginAt";
            break;
        case "3":
            System.out.println("Latest joined");
            field = "createdAt";
            break;
        case "4":
            System.out.println("Newest photo");
            field = "newestImageAt";
            break;
        case "5":
            System.out.println("Recently Updated");
            field = "updatedAt";
            break;
        default:
            System.out.println("default");
            field = "createdAt";
    }

    Query query = new Query();

    long totalUsercount = MongoApp.mongoOps().count(query, Person.class);

    //only show isActive users
    query.addCriteria(Criteria.where("isActive").is(true));

    //dont show yourself - loggedin user excluded from list
    query.addCriteria(Criteria.where("id").ne(loggedInUser.getId()));

    query.with(Sort.by(Sort.Direction.DESC, field));

    Pageable pageable = PageRequest.of(page, size);
    List<Person> totalPeople = new ArrayList<>();
    totalPeople = queryPeopleAddImages(totalPeople, query);
    long totalCount = totalPeople.size();
    query.with(pageable);

    // List People
    List<Person> people = new ArrayList<>();
    people = queryPeopleAddImages(people, query);

    BasicDBObject obj = userListResponse(loggedInUser, people, totalCount, totalUsercount);

    return obj;
}

我在这里添加了一些研究链接-我认为这些链接正在逐步完善这个功能
研究
How to write MongoDb Aggregation for this Criteria query

AggregationOperation match = Aggregation.match(Criteria.where("careGiverId").is(careTakerId).and("careType").is(careType));
 AggregationOperation count = Aggregation.count().as("count");
 Aggregation agg = Aggregation.newAggregation(match, count);
 mongoOperations.aggregate(agg, CareLogBean.class);

Spring MongoDB query sorting

AggregationOperation match = Aggregation.match(matching criteria);
AggregationOperation group = Aggregation.group("fieldname");
AggregationOperation sort = Aggregation.sort(Sort.Direction.ASC, "fieldname");
Aggregation aggregation = Aggregation.newAggregation(Aggregation.unwind("fieldname"),match,group,sort);

MongoDB print distance between two points

db.new_stores.aggregate([
    { "$geoNear": {
        "near": {
            "type": "Point",
            "coordinates": [ -81.093699, 32.074673 ]
        }, 
        "maxDistance": 500 * 1609,
        "key" : "myLocation",
        "spherical": true,
        "distanceField": "distance",
        "distanceMultiplier": 0.000621371
    }}
]).pretty()

“这允许您指定“distanceField”,它将在输出文档中生成另一个字段,其中包含与查询点的距离。您还可以使用“distanceMultiplier”根据需要对输出距离应用任何转换(即米到英里,并注意所有GeoJSON距离都以米为单位返回)
还有一个具有类似选项的geoNear命令,但它当然不会返回光标作为输出。
如果有多个2dsphere,则应指定“键”。
我有这个工作在前端计算距离公里
计算两个经纬度点之间的距离?(半正矢公式)
用半正矢公式

function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
  var R = 6371; // Radius of the earth in km
  var dLat = deg2rad(lat2-lat1);  // deg2rad below
  var dLon = deg2rad(lon2-lon1); 
  var a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
    Math.sin(dLon/2) * Math.sin(dLon/2)
    ; 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c; // Distance in km
  return d;
}

function deg2rad(deg) {
  return deg * (Math.PI/180)
}

2023年3月28日当前研究
我正在开发一个mongobdb应用程序-使用Java springboot。
它是一个用户网站--成员将登录并能够搜索/过滤/排序其他成员。
我已经开始构建一个带有基本查询的API--
我需要完成API的一部分,以允许您通过距离进行排序。每个用户都有lat/lng详细信息--我相信这是构建聚合查询的一个案例。
使用mongodb/java springboot通过登录用户和用户列表之间的距离进行排序的查询中的距离增加

  • 处理距离排序--聚合查询部分。
  • 我想清理代码库-因为有单独的api做类似/相同的搜索,但特定的过滤器- getUsers,getFavs,getBlocks,getViewedMe -
  • 也使分页选项可选-(或在其自己的函数中有一部分代码,以隔离它与可选的分页处理-又名减少重复的代码工作)-所以我可以获取所有用户数据,而不是它的块进行分析-再次类似的搜索/相同但可扩展-又名只提供5个最新的结果,提供分页数据与排序/过滤。
  • 能够添加多种类型的过滤器-与或操作-图像只,金发,蓝眼睛,种族

--所以你可以在这里看到--其他情况也可以--因为它们是实际的字段--- lastLoginAt,createdAt ----等等--而distance就像是一个需要创建的虚拟字段--我认为使用聚合

String field = "";//createdAt
switch (sort_by) {
case "1":
System.out.println("Distance");
break;
case "2":
System.out.println("Last online");
field = "lastLoginAt";
break;
case "3":
System.out.println("Latest joined");
field = "createdAt";
break;
case "4":
System.out.println("Newest photo");
field = "newestImageAt";
break;
case "5":
System.out.println("Recently Updated");
field = "updatedAt";
break;
default:
System.out.println("default");
field = "createdAt";
}

Query query = new Query();

long totalUsercount = MongoApp.mongoOps().count(query, Person.class);
System.out.println("totalUsercount "+ totalUsercount);

///default filters (only active users, no admins, no self)
query = addDefaultFilters(query, loggedInUser);
///default filters

//country filter
//query.addCriteria(Criteria.where("country").is("AR"));

query.with(Sort.by(Sort.Direction.DESC, field));

“MongoDB Compass终端,非常适合测试查询和聚合”

在这里添加了mongodb中的索引和2dsphere索引类型的文档。
2dshpere:https://www.mongodb.com/docs/manual/core/2dsphere/#:~:text= A%202dsphere%20index%20supports%20queries,geospatial%20queries%2C%20see%20Geospatial%20查询。索引:https://www.mongodb.com/docs/manual/indexes/
MongoDB的$geoNear聚合阶段需要2dsphere索引才能正确处理地理空间数据。这是因为$geoNear使用2dsphere索引来高效地执行地理空间查询
已经有一个默认的过滤器

public Query addDefaultFilters(Query query, Person loggedInUser) {

///default filters
//only show isActive users
query.addCriteria(Criteria.where("isActive").is(true));

//dont show admins
query.addCriteria(Criteria.where("role").ne("ROLE_ADMIN"));

//dont show yourself - loggedin user excluded from list
query.addCriteria(Criteria.where("id").ne(loggedInUser.getId()));
///default filters

return query;
}

--

Query query = new Query();

long totalUsercount = MongoApp.mongoOps().count(query, Person.class);
System.out.println("totalUsercount "+ totalUsercount);

///default filters (only active users, no admins, no self)
query = addDefaultFilters(query, loggedInUser);
///default filters

//country filter
//query.addCriteria(Criteria.where("country").is("AR"));

query.with(Sort.by(Sort.Direction.DESC, field));

Pageable pageable = PageRequest.of(page, size);
List totalPeople = new ArrayList();
totalPeople = queryPeopleAddImages(totalPeople, query);
long totalCount = totalPeople.size();
System.out.println("xxxxxxxxxxxxxtotalCount "+totalCount);
query.with(pageable);

// List People
//List people = MongoApp.mongoOps().findAll(Person.class);
List people = new ArrayList();
people = queryPeopleAddImages(people, query);

另一个java示例

x 1c 12d1x

3okqufwl

3okqufwl1#

我使用过MongoDB,而不是springboot,但据我所知,你的问题是你想在不同字段的聚合中进行排序/过滤。对吗?
对于排序,您可以用途:

collectionName.aggregate([
  {
    $match: {
     //... use the filter from the req body, just make sure that which fields you are filtering are introduced/used in aggregation.
    }
  },
  {
    $sort :{
     //... use the sorting option from the req body that will help you with custom fields, just make sure that which fields you are sorting are introduced/used before this portion of aggregation.
    }
  }
])

下面是用于排序的引用link

相关问题