我正在尝试对我在MongoDB中的文档集合执行$nearSphere
查询。在了解调用以类型化方式生成查询的特定方法之前,我使用了以下字符串插值法来自己创建查询,具体方法请参见在线文档:
var query = _col.Find($"{{ location: {{ $nearSphere: {{ $geometry: {{ type: \"Point\", coordinates: [ {lon}, {lat} ] }}, $maxDistance: {rad} }} }} }}");
这很好。我的查询是准确的。但是,在任何可能的地方,我都想改用类型化的方法,以便将来编译器为我提供帮助。因此,我在网上寻找了如何进行编码的方法,在阅读了之前的StackOverflow答案后,我想到了这个方法: / p>
var filter = Builders<Node>.Filter.NearSphere(n => n.Location, lon, lat, rad);
var query2 = _col.Find<Node>(filter);
问题在于,它们在后台生成了不同的查询,而后者生成的查询是不准确的。还有很多要点。
通过对生成的查询调用.ToString()
,我发现第一个查询变成了...
{find({ "location" : { "$nearSphere" : { "$geometry" : { "type" : "Point", "coordinates" : [1, 2] }, "$maxDistance" : 3 } } })}
...产生准确的结果。
第二个变成...
{find({ "location" : { "$nearSphere" : [1.0, 2.0], "$maxDistance" : 3.0 } })}
...格式不同,但无法产生准确的结果。
请注意,这里用于表示经度,纬度和半径的数字是示例,我的应用使用了我所在区域的实际值,可以通过检查OpenStreetMap数据进行确认。
答案 0 :(得分:0)
最终我自己解决了这个问题,将更多的时间花在了文档上并花了很多时间直到编译它。我发现很难在文档中找到解决方案,因为除了一小部分关于目前不支持地理空间查询与LINQ的内容外,他们没有执行地理空间查询的示例。
使用C#驱动程序的版本2.7
执行此类查询的代码为:
var filterPoint = GeoJson.Point(new GeoJson2DCoordinates(lon, lat));
var filter = new FilterDefinitionBuilder<Node>()
.NearSphere(n => n.Location, filterPoint, rad);
var query = _col.Find<Node>(filter);
我还必须确保我在模型(用于执行查询的类)中使用了MongoDB GeoJSON点数据类型:
public class Node
{
[BsonElement("_id")]
public long Id { get; set; }
[BsonElement("location")]
public GeoJsonPoint<GeoJson2DCoordinates> Location { get; set; }
[BsonElement("tags")]
public BsonDocument Tags { get; set; }
}
请注意,Tags
属性代表任何JSON类型,因此我使用BsonDocument
。返回响应后,我可以将其映射到Dictionary<string, object
。
仅是为了向阅读本文的任何人提供一个更完整的示例,这是我在准备运行查询后将其使用,将结果映射到我的DTO并在ASP.NET Core 2.1中发送200响应后使用的代码: / p>
// Perform query and map to DTO
var res = (await query.ToListAsync()).Select(n =>
{
var lonLat = n.Location.Coordinates.Values.ToArray();
return new NodeBase
{
Id = n.Id.ToString(),
Location = new SimpleGeoJsonPoint
{
Lon = lonLat[0],
Lat = lonLat[1],
},
Tags = n.Tags.ToDictionary(),
};
});
return Ok(new MultiSearchResult<NodeBase>
{
Count = res.Count(),
Results = res,
});
请注意,NodeBase
是我的DTO,用于在我的Node
文档执行搜索时将其返回给客户端。 SimpleGeoJsonPoint
是我在其他DTO中使用的DTO,用于以简单的方式表示GeoJSON点。我不需要绒毛,只有经度和纬度。 MultiSearchResult<T>
是我的通用DTO,用于将搜索结果返回给客户端。