【问题标题】:maxDistance parameter of Query.Near not workingQuery.Near 的 maxDistance 参数不起作用
【发布时间】:2013-12-31 02:01:55
【问题描述】:

我正在使用 MongoDB 的 C# 驱动程序,并试图让 Query.Near 工作,以便在距离中心点 5、10、25 或 50 英里范围内返回待售房屋。这是查询:

var near = Query.Near("Coordinates", coordinates.Latitude, coordinates.Longitude, find.GetRadiansAway(), false);
    //var near = Query.WithinCircle("Coordinates", coordinates.Latitude, coordinates.Longitude, find.GetRadiansAway(), false);
    var query = Collection().Find(near);
    query.Limit = 1000;
    var listings = query.ToList();

我将英里半径除以 62.1868289 以获得弧度并将其输入到查询中,但是无论我传入什么弧度值,它都会返回相同数量的待售房屋。我还尝试了设置球形参数为 true 并使用 Query.WithinCircle,但两者都没有更好的效果。

我正在使用最新的 C# 驱动程序 (1.0.0.4098),这是 C# 驱动程序中的错误,MongoDB 中的错误,还是我在这里遗漏了什么?

查询如下所示:

5 英里外(近):

db.Listing.find({ "Coordinates" : { "$near" : [39.4812172, -76.6438598], "$maxDistance" : 0.072463768115942032 } });

10 英里外(近):

db.Listing.find({ "Coordinates" : { "$near" : [39.4812172, -76.6438598], "$maxDistance" : 0.14492753623188406 } });

5 英里外(近球形):

db.Listing.find({ "Coordinates" : { "$nearSphere" : [39.4812172, -76.6438598], "$maxDistance" : 0.0012629451881788331 } });

10 英里外(近处为球形):

db.Listing.find({ "Coordinates" : { "$nearSphere" : [39.4812172, -76.6438598], "$maxDistance" : 0.0025258903763576662 } });

这是我的测试用例,无论我在 5 英里外还是 25 英里外通过,它都会返回相同数量的结果:

[Test]
        public void NearTest()
        {
            var isSpherical = true;
            var latitude = 39.4812172;
            var longitude = -76.6438598;
            var milesAway = 5;
            var distance = milesAway / (isSpherical ? 3959.0 : 69.0);

            //search within 5 miles.
            var near = Query.Near("Coordinates", latitude, longitude, distance, isSpherical);
            var collection = ContextWorker.Database.GetCollection<Schemas.Listing.Listing>("Listing");
            var query = collection.Find(near);
            query.Limit = 1000;
            var listings = query.ToList();
            var count1 = listings.Count;
            //Console.WriteLine("query: {0}", query.ToJson());
            Console.WriteLine(count1 + " results returned that are " + milesAway + " miles away");

            //search within 25 miles.
            milesAway = 25;
            distance = milesAway / (isSpherical ? 3959.0 : 69.0);
            near = Query.Near("Coordinates", latitude, longitude, distance, isSpherical);
            query = collection.Find(near);
            query.Limit = 1000;
            listings = query.ToList();
            var count2 = listings.Count;
            //Console.WriteLine("query: {0}", query.ToJson());
            Console.WriteLine(count2 + " results returned that are " + milesAway + " miles away");

            //values should be different.
            Assert.AreNotEqual(count1, count2, "Returned same results for 5 and 25 miles away");
        }

172 results returned that are 5 miles away
172 results returned that are 25 miles away
Test 'Housters.Test.SearchTest.NearTest' failed: 
  Returned same results for 5 and 25 miles away
  Expected: not 172
  But was:  172
    SearchTest.cs(68,0): at Housters.Test.SearchTest.NearTest()

【问题讨论】:

    标签: mongodb mongodb-.net-driver


    【解决方案1】:

    这里有一堆问题:

    1. 几乎所有的 Mongo 地理空间查询都首先采用 x 坐标(经度)。
    2. 当您不使用球面查询时,Mongo 只会计算简单的笛卡尔距离,而您需要传递的距离与您的坐标采用相同的单位(可能是十进制度数)。
    3. 如果您确实使用球形查询(接近或内部),则需要以弧度指定距离,但要将英里转换为弧度,则需要除以更大的数量超过 62.1868289。除以地球的半径(约 3,959 英里)即可将弧度转换为英里。

    您在上面执行的转换实际上更接近从英里到度的转换(以英里为单位的距离除以大约 69)。

    【讨论】:

    • 感谢您的回复。我在我的 Listing.Coordinates 对象中有纬度,所以我首先将纬度传递给函数。在第 3 点中,您谈到从弧度转换为英里,但是我需要从英里转换为弧度。你知道这样做的公式吗?还是 #2 的公式,从英里转换为十进制度?
    • 我确实包括了从英里到弧度的转换:您将距离以英里为单位除以 3959 以(大致)将其转换为弧度。显然你会得到一个非常小的数字,但请记住,弧度很大(地球的整个圆周只有 6 弧度多一点)。
    • 我用弧度(英里除以 3959)和非球形近用度数(英里除以 69)都试过了,两者的表现都和我看到的完全一样现在,无论我输入什么半径,它都会返回相同的房屋区域。
    • 我已经修改了我的问题,它为近端和球面近端生成的查询。
    【解决方案2】:

    确定问题出在 C# 驱动程序还是查询本身的一个好方法是首先让查询在 mongo shell 中工作。然后,您可以使用 C# 查询生成器编写等效查询。作为最后的检查,您可以看到等效的 JSON 查询如下:

    var query = Query.Near(...); var json = query.ToJson();

    您能否提供一些您认为应该退回的示例文件?

    【讨论】:

    • @Robert mongo shell 的难点在于,当我运行查询时,它最多只能返回 100 个结果。即使是 count 方法也最多只能返回 100。所以当我测试传递不同的距离时,对于其中许多它只返回 100,所以我不知道当我增加范围时它是否返回更多。
    • 这个例子有几点: 1. 调用 query.ToJson() 方法给了我这个错误 - “没有找到类型的序列化程序:MongoDB.Driver.IMongoFields”。 2. 我不能使用 query.WithinCircle,因为它没有按到中心的距离对结果进行排序。
    • 你所说的查询变量应该叫游标。您想在查询对象上调用 ToJson,而不是在游标上(换句话说,在 Find 的查询参数上,而不是 Find 的返回值上)。
    • @Robert 嘿,我刚刚更改了您的测试用例,首先切换到纬度,然后切换到经度 - pastie.org/1916897 - 因为这是我的数据的格式。它在 mongodb 文档中说 - “其中前 2 个元素是 x,y 坐标(或 y,x - 只是保持一致)” - 所以首先纬度应该没问题,但是测试用例失败了。这是我的问题吗,我的数据中没有经度优先?
    • 如果您希望结果按距离排序,另一种方法是使用 GeoNear 命令。请参阅:pastie.org/1916916
    猜你喜欢
    • 2017-07-18
    • 1970-01-01
    • 2013-12-19
    • 2012-11-18
    • 2019-07-06
    • 1970-01-01
    • 1970-01-01
    • 2012-11-17
    • 2011-11-10
    相关资源
    最近更新 更多