【问题标题】:Geospatial and Morphia not find by near附近找不到地理空间和 Morphia
【发布时间】:2015-10-25 09:19:47
【问题描述】:

我有以下数据库:

db.ItemVo.find()

{ "_id" : ObjectId("55bf2b465ef98ff39dba049c"), "loc" : { "type" : “点”,“坐标”:[-4.427237, 36.733284] },“标题”: “item1”、“summary”:“摘要 item1”、“itemType”:“TXT”} {“_id”: ObjectId(“55bf2ddc5ef98ff39dba049d”),“loc”:{“type”:“Point”, “坐标”:[-3.427237, 35.733284] },“标题”:“item2”, "summary" : "总结 item2", "itemType" : "TXT" }

按 $near 查找:

db.ItemVo.find({loc:{"$near":{ "$geometry": {type: "Point", 坐标:[-4.427, 36.73]},“$maxDistance”:20000}}})

{ "_id" : ObjectId("55bf2b465ef98ff39dba049c"), "loc" : { "type" : “点”,“坐标”:[-4.427237, 36.733284] },“标题”: "item1", "summary" : "摘要 item1", "itemType" : "TXT" }

在 Morphia DAO 中:

public List<ItemVo> findByNear (){
    LOGGER.info("[ItemDAO - findByNear] - init");

    List<ItemVo> str = getDs().find(ItemVo.class).field("loc").near(-4.427, 36.73,  2000/111.12, true).asList();
    return str;
}

Morphia 返回集合的所有元素,而不是通过 $near 找到的。 Morphia 应该只返回元素“item1”而不是“item2”。问题出在哪里?

我的对象:

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
Public class ItemVo implements Serializable{

        private static final long serialVersionUID = 1258690003100456384L;

        @Id private String id;

        @Embedded
        private LocationVo loc;

        private String title;
        private String summary;

........

@Embedded
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class LocationVo implements Serializable{

    private static final long serialVersionUID = -5282690346503247312L;

    private String type; //POINT, etc
    private double[] coordinates;

谢谢。

【问题讨论】:

    标签: java mongodb geospatial morphia


    【解决方案1】:

    好的。我已经找到了它,它很简单。由于我无法理解的原因,mongo shell 采用 lat/long 坐标,而 morphia 采用 long/lat 坐标。因此,虽然它看起来就像您在 morphia 中忠实地重新创建查询,但实际上您的坐标是向后定义的。尝试交换您的值,您应该会开始看到您期望的文档。

    【讨论】:

      【解决方案2】:

      @evanchooly 不起作用。目前数据:

      { "_id" : ObjectId("55bf2b465ef98ff39dba049c"), "loc" : { "type" : “点”,“坐标”:[-4.427237, 36.733284] },“标题”: “item1”,“summary”:“摘要 item1”,“itemType”:“TXT”} {“_id”: ObjectId(“55bf2ddc5ef98ff39dba049d”),“loc”:{“type”:“Point”, “坐标”:[-3.427237, 35.733284] },“标题”:“item2”, “摘要”:“摘要 item2”,“itemType”:“TXT”} {“_id”: ObjectId(“55bf419d79711904641950e3”),“loc”:{“type”:“Point”, “坐标”:[-2.427237, 36.733284]},“标题”:“item3”, “摘要”:“摘要 item3”,“itemType”:“TXT”} {“_id”: ObjectId(“55bf74bd7971191d180d67ad”),“loc”:{“type”:“Point”, “坐标”:[-5.427237, 35.733284]},“标题”:“item4”, "summary" : "总结 item4", "itemType" : "TXT"}

      geo[0]=-4.4272;
      geo[1]=36.733;
      

      使用 lat/long(和以前一样)Morphia 返回所有元素,尽管半径是 2/111.12 或 20000/111.12。

      如您所说,使用 long/lat,Morphia 返回半径从 2/111.12 到 107/111.12 的空列表。半径为 108/111.12 返回 item2 和 item3。半径从 109/111.12 到 20000/111.12 返回所有元素。

      我不明白为什么。我认为也许 Morphia 的查询不太好,Morphia 没有找到“loc”,所以 Morphia 返回所有。我一直在搜索google,查询应该没问题。

      编辑:

      如果我在 mongo 控制台中运行以下命令:

      db.runCommand ( {geoNear: "ItemVo", near : [-4.427, 36.733 ] , maxDistance: 20000, spherical:true }) 
      

      每个返回的元素都包含距离。例如:

      {“dis”:0.00000596312302919342,“obj”:{“_id”: ObjectId("55bf2b465ef98ff39dba049c"), ... ... } },

      我不明白为什么距离值与通话不同:

      db.ItemVo.find({loc:{"$near":{ "$geometry": {type: "Point", coordinates: [-4.427, 36.73]}, "$maxDistance": 20000}}})
      

      【讨论】:

      • Morphia 不会做任何此类事情。它将您的查询传递给服务器并返回服务器所做的任何事情。它不仅仅决定您的数据。我不是地理专家,但这些半径对我来说似乎有点小,所以我并不完全惊讶于较小的值没有任何回报。
      • (我用这条评论编辑了我的答案)如果我在 mongo 控制台中运行以下命令: db.runCommand ( {geoNear: "ItemVo", near : [-4.427, 36.733 ] , maxDistance: 20000 ,spherical:true }) 每个返回的元素都包含距离。例如: { "dis" : 0.00000596312302919342, "obj" : { "_id" : ObjectId("55bf2b465ef98ff39dba049c"), ... ... } },我不明白为什么距离值与调用不同: db.ItemVo.find({loc:{"$near":{ "$geometry": {type: "Point", 坐标: [-4.427, 36.73]}, "$maxDistance": 20000}}})跨度>
      • 我认为区别在于spherical: true。要么不通过,要么将其设置为 false,然后看看有什么不同。 (我不是地理专家,所以我正在挖掘这些年来我听到的随机花絮。)
      【解决方案3】:

      我最近解决了这个问题,并希望将解决方案提供给有相同问题的其他人。我不知道为什么它现在可以工作,也许是因为我使用了更新版本的 Morphia。小米码:

      public List<ItemVo> findItems (Double latitude, Double longitude, Double radius){
          LOGGER.info("[ItemDAO - findItems] - init");
          str = getDs().createQuery(ItemVo.class).field("loc").near(latitude, longitude,  radius/111.12, true).asList();
          return str;
      }
      

      在 webservice 中接收到参数“radius”(整数,以千米为单位),我们在调用 itemDAO.findItems 之前对其进行转换:

      //private static Double FORMAT_RADIUS = 0.01;
      
      Double radius_format = radius * FORMAT_RADIUS;
      

      【讨论】:

      • 我会说,应该交换纬度/经度。根据this,首先是longitude,然后是latitude
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 2019-08-31
      • 2023-03-26
      • 2021-11-07
      • 2012-01-04
      • 2014-09-16
      相关资源
      最近更新 更多