【发布时间】:2021-04-18 13:18:38
【问题描述】:
我们正在从 MongoDb 迁移到 RavenDb,但遇到了问题。
我们有一个简单的模型(C# DotNet)
using System.Globalization;
public class Location
{
#region Properties
public double Latitude { get; set; }
public double Longitude { get; set; }
#endregion Properties
#region Methods
public override string ToString()
{
var numberFormatInfo = new NumberFormatInfo { NumberDecimalSeparator = "." };
return $"{Longitude.ToString(numberFormatInfo)} {Latitude.ToString(numberFormatInfo)}";
}
#endregion Methods
}
public class Place
{
public Location[] Area {get;set;} // Please note the array
}
客户可以选择一个地点作为一对,也可以在交互式地图上绘制一个多边形来表示该地点,该多边形将存储在上面的 Area 属性中。
在 MongoDb 中,这再简单不过了
var locationQuery = new FilterDefinitionBuilder<Place>()
.GeoWithinBox(
field: x => x.Area,
lowerLeftX: query.Criteria.LongitudeBottomLeft,
lowerLeftY: query.Criteria.LatitudeBottomLeft,
upperRightX: query.Criteria.LongitudeTopRight,
upperRightY: query.Criteria.LatitudeTopRight);
上面的查询类,代表了地图上当前可见的区域,客户正在查看。
尽管我尽了最大努力,但我无法破译有关如何实现相同目标的文档。 我希望有人能够对此事有所了解,关于如何使用 RavenDb Dotnet 客户端 (RavenDB.Client)
谢谢
更新和示例!
在下面 Ayende Rahien 的精彩回答之后,我想我会在这里添加一些细节,以简化其他人登陆这里的旅程。
这就是索引的样子。
using System.Linq;
using Raven.Client.Documents.Indexes;
public class PlaceAreaIndex : AbstractIndexCreationTask<Place>
{
public PlaceAreaIndex()
{
Map = places => from place in places
select new
{
Area = place.Area.Select(location => CreateSpatialField(location.Latitude, location.Longitude))
};
}
}
在使用查询之前,您需要在服务器上注册您的索引。
new PlaceAreaIndex().Execute(store);
我添加了一些帮助类来帮助我进行测试,我在这里添加它们是为了让示例让您尽可能接近正在运行的代码
public class Box
{
#region Constructor
public Box(Location topRight, Location bottomLeft)
{
TopRight = topRight;
BottomLeft = bottomLeft;
TopLeft = new Location { Latitude = topRight.Latitude, Longitude = bottomLeft.Longitude };
BottomRight = new Location { Latitude = bottomLeft.Latitude, Longitude = topRight.Longitude };
}
#endregion Constructor
#region Properties
public Location TopRight { get;}
public Location TopLeft { get; }
public Location BottomLeft { get; }
public Location BottomRight { get; }
#endregion Properties
#region Methods
public override string ToString()
{
return $"POLYGON (({TopRight}, {TopLeft}, {BottomLeft}, {BottomRight}, {TopRight}))";
}
#endregion Methods
}
然后使用助手
var topRight = Location.New(latitude: -22.674847351188916, longitude: 31.25061035156253);
var bottomLeft = Location.New(latitude: -28.9600886880069, longitude: 25.1422119140623);
var box = new Box(topRight: topRight, bottomLeft: bottomLeft);
之后就可以这样查询了
var places = await session
.Query<Place, PlaceAreaIndex>()
.Spatial(
factory => factory.Area,
criteria => criteria.RelatesToShape(
shapeWkt: box.ToString(),
relation: SpatialRelation.Within))
.ToArrayAsync();
希望对你有帮助。
【问题讨论】:
-
您可以在此处看到一个查询多边形区域的动态查询示例:github.com/ravendb/ravendb/blob/… 注意:多边形起点和终点位置必须相同,并且点必须按逆时针顺序
-
嗨丹妮尔,谢谢你的链接。我确实看到了那个,但仍然无法弄清楚它如何应用于正在存储的数组。