2017-06-18 53 views
1

我使用蔚蓝宇宙分贝如何创建索引和查询最近的前10名用户,如果该文件是这样的,在C#:创建地理索引和查询附近

{ 
    "_id" : "146138792054898475572", 
    "email" : "[email protected]", 
    "firstName" : "abc", 
    "lastName" : "abc", 
    "loc" : { 
    "lat" : 31.5200788, 
    "lng" : 74.3236112 
    }, 
    "gender" : "Male", 
    "deviceId" : "YWg8crAjZLCrV", 
    "createdDate" : ISODate("2017-06-11T11:35:41.601Z"), 
    "updatedDate" : ISODate("2017-06-17T17:33:10.743Z") 
} 

查询:

db.User.find(
    { 
     "loc": 
     { $near : 
      { 
      $geometry: { type: "Point", coordinates: [ 31.5200788, 74.3236112 ] }, 
      $minDistance: 1000, 
      $maxDistance: 5000 
      } 
     } 
    } 
) 
+0

所以你试图做一个空间查询?你尝试了什么?您只显示了文档,没有查询尝试,没有输出,也没有发生特定的错误。您的数据库是否设置为DocumentDB API或MongoDB API?这是一个很大的区别。我猜测MongoDB基于属性和标签,但你应该确认。 –

+0

@DavidMakogon querry添加了 –

+0

没有结果显示,当我尝试这 –

回答

2

有一对夫妇在这里的问题,主要是涉及到你是如何存储的文件。 MongoDB的支持存储在三种格式之一的坐标点:

  • 旧坐标对作为阵列当数据在经度列出然后纬度顺序

    [ 74.3236112, 31.5200788 ] 
    
  • 旧坐标对作为对象其中数据可以由名为键来组织,但这些必须订购并明确命名为“LON”“LAT”分别 “以”:

    { "lon": 74.3236112, "lat": 31.5200788 } 
    
  • 作为GeoJSON格式其中存储的数据可以是任何有效GeoJSON的对象的格式。对于“点”类型是这样的:

    { 
        "type": "Point", 
        "coordinates": [ 74.3236112, 31.5200788 ] 
    } 
    

为了证明我有一个集合,在四种不同的格式示例文档。我们要创建的是集合的索引与.createIndex({ "loc": "2dsphere" }),然后使用聚合管道$geoNear查询,并从查询点返回的实际距离:

db.geotest.aggregate([ 
    { "$geoNear": { 
    "near": { 
     "type": "Point", 
     "coordinates": [ 74.3236112, 31.5200788 ] 
    }, 
    "spherical": true, 
    "distanceField": "distance" 
    }} 
]) 

显示从查询中四种不同的格式和计算的距离。请注意,只有两个“有效”格式从查询地点返回0正确的距离:

{ 
     "_id" : ObjectId("5945f800b4051c7e52c90d1c"), 
     "email" : "[email protected]", 
     "firstName" : "abc", 
     "lastName" : "abc", 
     "loc" : { 
       "type" : "Point", 
       "coordinates" : [ 
         74.3236112, 
         31.5200788 
       ] 
     }, 
     "gender" : "Male", 
     "deviceId" : "YWg8crAjZLCrV", 
     "createdDate" : ISODate("2017-06-11T11:35:41.601Z"), 
     "updatedDate" : ISODate("2017-06-17T17:33:10.743Z"), 
     "distance" : 0 
} 
{ 
     "_id" : ObjectId("5945f8f6b4051c7e52c90d1e"), 
     "email" : "[email protected]", 
     "firstName" : "abc", 
     "lastName" : "abc", 
     "loc" : { 
       "lon" : 74.3236112, 
       "lat" : 31.5200788 
     }, 
     "gender" : "Male", 
     "deviceId" : "YWg8crAjZLCrV", 
     "createdDate" : ISODate("2017-06-11T11:35:41.601Z"), 
     "updatedDate" : ISODate("2017-06-17T17:33:10.743Z"), 
     "distance" : 0 
} 
{ 
     "_id" : "146138792054898475572", 
     "email" : "[email protected]", 
     "firstName" : "abc", 
     "lastName" : "abc", 
     "loc" : { 
       "lat" : 31.5200788, 
       "lng" : 74.3236112 
     }, 
     "gender" : "Male", 
     "deviceId" : "YWg8crAjZLCrV", 
     "createdDate" : ISODate("2017-06-11T11:35:41.601Z"), 
     "updatedDate" : ISODate("2017-06-17T17:33:10.743Z"), 
     "distance" : 5315650.25629941 
} 
{ 
     "_id" : ObjectId("5945f8b7b4051c7e52c90d1d"), 
     "email" : "[email protected]", 
     "firstName" : "abc", 
     "lastName" : "abc", 
     "loc" : { 
       "lat" : 31.5200788, 
       "lon" : 74.3236112 
     }, 
     "gender" : "Male", 
     "deviceId" : "YWg8crAjZLCrV", 
     "createdDate" : ISODate("2017-06-11T11:35:41.601Z"), 
     "updatedDate" : ISODate("2017-06-17T17:33:10.743Z"), 
     "distance" : 5315650.25629941 
} 

因此为了正确查询,你需要一个“有效”为索引格式。我个人建议使用GeoJSON格式,因为它被广泛用作标准,并且还可以选择存储任何有效的GeoJSON对象,而不仅仅是“点坐标”

您可以操作的数据转换如下所示:

var ops = []; 

db.User.find({ 
    "loc.lng": { "$exists": true }, 
    "loc.lat": { "$exists": true } 
}).forEach(function(doc) { 
    ops.push({ 
    "updateOne": { 
     "filter": { "_id": doc._id }, 
     "update": { 
     "$set": { 
      "loc": { 
      "type": "Point", 
      "coordinates": [ doc.loc.lng, doc.loc.lat ] 
      } 
     } 
     } 
    } 
    }); 
    if (ops.length >= 1000) { 
    db.User.bulkWrite(ops); 
    ops = []; 
    } 
}); 

if (ops.length > 0) { 
    db.User.bulkWrite(ops); 
    ops = []; 
} 

这将"loc"数据重新写入修正后的格式,以便在索引和查询会工作。

实际上,在更新之前,您应该在集合上确实执行.dropIndexes()以节省写入成本,然后在完成后重新创建索引。这不是一个必要的步骤,但它会被推荐。

N.B还具有校正实际上将仍然排除的结果,因为所证明从查询点(这是相同的坐标)的实际距离数据的$minDistace参数这里是0。所以在测试中删除这个约束,或者更好地用$geoNear进行测试。

另请注意有提及的DocumentDB,它不支持聚合流水线协议。这里的例子对MongoDB没有问题,主要是为了演示数据的“格式”问题。常规$nearother geospatial general queries are supported。但数据必须采用正确的支持格式。

2

你的坐标是落后的。每MongoDB的docs: 经度,纬度:

如果使用经度和纬度,在顺序指定坐标。

你需要扭转你的坐标:

db.User.find(
    { 
     "loc": 
     { $near : 
      { 
      $geometry: { type: "Point", coordinates: [ 74.3236112, 31.5200788 ] }, 
      $minDistance: 1000, 
      $maxDistance: 5000 
      } 
     } 
    } 
) 

而且,在你的loc财产,顺序是经度,纬度(你在你表现出的文档相反)。

+0

仍然没有结果 –

+0

@MalikKashmiri这里的p​​romlem是'$ maxDistance:5000',因为问题文档中给出的点比提供的约束更“进一步”。使用经度和纬度的正确顺序删除该查询,然后查询返回文档。 –