RavenDb空间查询

c#

我们正在从 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();

希望对你有帮助。

以上是RavenDb空间查询的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>