簡體   English   中英

如何在 2.1 MongoDB C# 驅動程序中使用地理空間查詢?

[英]How do I use a geospatial query in the 2.1 MongoDB C# driver?

幾天來我一直在用這個頭撞。 我有一個非常簡單的查詢,我試圖在 C# 中運行,它在 shell 中看起來像這樣。

db.runCommand({geoNear: "items", near: {type: "Point", coordinates : [-111.283344899999, 47.4941836]}, spherical : true, distanceMultiplier: 3963.2, maxDistance : 25});

我的收藏看起來像這樣

{    
  "_id" : ObjectId(),    
  "Title" : "arst",    
  "Description" : "<p>arst</p>",    
  "Date" : new Date("11/29/2015 09:28:15"),    
  "Location" : {    
    "type" : "Point",    
    "Coordinates" : [-111.28334489999998, 47.4941836]    
  },    
  "Zip" : "59405"    
}

根據此處的文檔MongoDB C# API Docs MongoDB.Driver.Builders.Query 對象現在是遺留的。 所以當我做這樣的事情時

 var point = new GeoJson2DGeographicCoordinates(double.Parse(longitude), double.Parse(latitude)) ;
        var query = Query<Item>.Near(x => x.Location, new GeoJsonPoint<GeoJson2DGeographicCoordinates>(point), distance, true);

        var result = collection.Find(query);

編譯器抱怨它無法從 IMongoQuery 轉換為 FilterDefinition。 這告訴我新的 2.1 庫不支持舊版 Query<> 構建器。 但是在我的一生中,我在 api 文檔中找不到任何引用替代品的地方?

任何人都可以指出我在 2.1 C# 驅動程序中執行這個簡單的地理空間查詢的正確方向嗎? 我難住了。

另外,我確實在集合上創建了一個 2dsphere 索引,如果我不這樣做,shell 命令將無法工作。 這是索引輸出。

{
            "v" : 1,
            "key" : {
                    "Location.Coordinates" : "2dsphere"
            },
            "name" : "Location.Coordinates_2dsphere",
            "ns" : "ppn.items",
            "2dsphereIndexVersion" : 2
    }

編輯

在挖掘了大量文檔之后,我想我找到了它。 所有示例仍然顯示舊的 Query<> 方法,但新方法似乎是 Builders<>.Filter 命名空間的一部分。 所以這個代碼塊似乎對我有用,

 double lng = double.Parse(longitude);
 double lat = double.Parse(latitude);
 point = new GeoJson2DGeographicCoordinates(lng, lat);
 pnt = new GeoJsonPoint<GeoJson2DGeographicCoordinates>(point);
 dis = distance * 1609.34;
 fil = Builders<Item>.Filter.NearSphere(p => p.Location.Coordinates, pnt, dis);

 filter = filter & fil;

 var sort = Builders<Item>.Sort.Descending("Date");

 // This is the actual query execution
 List<Item> items = collection.Find(filter).Sort(sort).ToListAsync().Result;

這個代碼塊很亂,它是反復嘗試和失敗的結果。 我相信我會想辦法清理它。 對我來說,您必須從 GeoJson2DGeographicCoordinates 創建一個 GeoJsonPoint 似乎有點冗長,但我相信這是有充分理由的。 如果有人知道,請隨時發表評論。 任何有關改進此答案的建議都非常受歡迎,這是對文檔的令人沮喪的挖掘,因此希望這有助於為其他人指明正確的方向。

這就是我最后的做法:

    public IQueryable<TEntity> FindNear<TEntity>(string collectionName, Expression<Func<TEntity, object>> field, double longitude, double latitude, double maxDistanceInKm) where TEntity : IEntity
    {
        var collection = database.GetCollection<TEntity>(collectionName);
        var point = GeoJson.Point(GeoJson.Geographic(longitude, latitude));
        var filter = Builders<TEntity>.Filter.Near(field, point, maxDistanceInKm * 1000);
        return collection.Find(filter).ToList().AsQueryable();
    }

這是對任何感興趣的人進行地理空間聚合查詢的最方便的方法:

using MongoDB.Driver;
using MongoDB.Entities;
using System;

namespace StackOverflow
{
    public class Program
    {
        public class Place : Entity
        {
            public string Name { get; set; }
            public DateTime Date { get; set; }
            public Coordinates2D Location { get; set; }
            public double DistanceMeters { get; set; }
        }

        static void Main(string[] args)
        {
            //connect to mongodb
            new DB("test");

            //create a geo2dsphere index
            DB.Index<Place>()
              .Key(x => x.Location, KeyType.Geo2DSphere)
              .Option(x => x.Background = false)
              .Create();

            //create and save a place
            var paris = new Place
            {
                Name = "paris",
                Location = new Coordinates2D(48.8539241, 2.2913515),
                Date = DateTime.UtcNow
            };
            paris.Save();

            var eiffelTower = new Coordinates2D(48.857908, 2.295243);

            //find all places within 1km of eiffel tower.
            var places = DB.GeoNear<Place>(
                              NearCoordinates: eiffelTower,
                              DistanceField: x => x.DistanceMeters,
                              MaxDistance: 1000)
                           .SortByDescending(x=>x.Date)
                           .ToList();
        }
    }
}

它生成以下聚合管道:

{
                "$geoNear": {
                    "near": {
                        "type": "Point",
                        "coordinates": [
                            48.857908,
                            2.295243
                        ]
                    },
                    "distanceField": "DistanceMeters",
                    "spherical": true,
                    "maxDistance": NumberInt("1000")
                }
            },
            {
                "$sort": {
                    "Date": NumberInt("-1")
                }
            }

以上是使用MongoDB.Entities便利庫完成的,我是其中的作者。

我就是這樣做的。 它非常簡單,並且能夠將查詢從 mongo shell 復制並粘貼到查詢變量中。

對於簡單的查找,如果在 100 米內,則返回 1 個文檔:

var nearSphereQuery = "{location: { $nearSphere: {$geometry: { type: \"Point\", coordinates: [-1.50,53.50]},  $maxDistance: 100}} }";
var nearSphereBsonDoc = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(nearSphereQuery);
var result = points.Find(nearSphereBsonDoc).Limit(1).SingleOrDefault();
if (result != null) {
    // do stuff here
} else {
    // nothing found
}

要獲取與同一請求的搜索點的距離:

var geoNearQuery = "{$geoNear: { near: { type: \"Point\", coordinates: [-1.50, 53.50]}, spherical: true, distanceField: \"distance\"} } ,{$match: { distance: { $lt: 100} } }";
var geoNearBsonDoc = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(geoNearQuery);
var pipeline = new List<BsonDocument>();
var matchQuery = "{ $match: { distance: { $lt: 10} } }";
var matchBsonDoc = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(matchQuery);
var pipeline = new List<BsonDocument>();
pipeline.Add(geoNearBsonDoc);
pipeline.Add(matchBsonDoc);   
pipeline.Add(new BsonDocument { { "$limit", 1 } });
var result = points.Aggregate<BsonDocument>(pipeline).SingleOrDefault();
if (result != null) {
    Double dist = Convert.ToDouble(result["distance"]);
} else {
    // nothing found
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM