Description
If we create multiple geo conditions on the same field in one query, and one condition is the near operator. The driver don't translate this to a correct MongoDb query. The following code demonstrate the behaviour. And the result and exception message is as comments.
using MongoDB.Bson;
|
using MongoDB.Bson.Serialization;
|
using MongoDB.Driver;
|
using MongoDB.Driver.GeoJsonObjectModel;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;namespace MongoDbJira
|
{
|
class Program |
{
|
static void Main(string[] args) |
{
|
var client = new MongoClient("mongodb://localhost"); |
var database = client.GetDatabase("testdb"); |
database.DropCollection("test"); |
var collection = database.GetCollection<BsonDocument>("test"); |
var indexModel = new CreateIndexModel<BsonDocument>(new IndexKeysDefinitionBuilder<BsonDocument>().Geo2DSphere("geoField")); |
collection.Indexes.CreateOne(indexModel); collection.InsertOne(BsonDocument.Parse("{'geoField':{'type':'Point','coordinates':[18.07309566753327, 59.31119815301082]}, 'name':'A'}")); |
collection.InsertOne(BsonDocument.Parse("{'geoField':{'type':'Point','coordinates':[18.031779179282793 59.31869226401174]} 'name':'B'}")); |
|
var filterDefinitions = new List<FilterDefinition<BsonDocument>>(); |
filterDefinitions.Add(Builders<BsonDocument>.Filter.GeoWithinBox("geoField", 18.02768052426505, 59.302264601734144, 18.103211530124426, 59.32407863571196)); |
filterDefinitions.Add(Builders<BsonDocument>.Filter.Near("geoField", new GeoJsonPoint<GeoJson2DCoordinates>(new GeoJson2DCoordinates(18.07176, 59.31395)), 500)); |
var filterDefinition = Builders<BsonDocument>.Filter.And(filterDefinitions);
|
var failingFilterDefinitionAsString = filterDefinition.Render(BsonSerializer.SerializerRegistry.GetSerializer<BsonDocument>(), BsonSerializer.SerializerRegistry).ToString();
|
Console.WriteLine(failingFilterDefinitionAsString); //{ "geoField" : { "$geoWithin" : { "$box" : [[18.027680524265051, 59.302264601734144], [18.103211530124426, 59.324078635711963]] }, "$near" : { "$geometry" : { "type" : "Point", "coordinates" : [18.071760000000001, 59.313949999999998] }, "$maxDistance" : 500.0 } } } try |
{
|
var failingFindResult = collection.Find(filterDefinition).ToList();
|
}
|
catch (Exception e) |
{
|
Console.WriteLine(e.Message); //Command find failed: can't parse extra field: $near: { $geometry: { type: "Point", coordinates: [ 18.07307303636145, 59.31128165641481 ] }, $maxDistance: 500.0 }. |
}
|
var myFilterBuilder = new StringBuilder(); |
myFilterBuilder.Append("{$and:["); |
for (int i = 0; i < filterDefinitions.Count; i++) |
{
|
if (i > 0) |
{
|
myFilterBuilder.Append(","); |
}
|
myFilterBuilder.Append(filterDefinitions.ElementAt(i).Render(BsonSerializer.SerializerRegistry.GetSerializer<BsonDocument>(), BsonSerializer.SerializerRegistry).ToString());
|
}
|
myFilterBuilder.Append("]}"); |
var successfulFilterDefintionAsString = BsonSerializer.Deserialize<BsonDocument>(myFilterBuilder.ToString());
|
Console.WriteLine(successfulFilterDefintionAsString); //{{ "$and" : [{ "geoField" : { "$geoWithin" : { "$box" : [[18.027680524265051, 59.302264601734144], [18.103211530124426, 59.324078635711963]] } } }, { "geoField" : { "$near" : { "$geometry" : { "type" : "Point", "coordinates" : [18.071760000000001, 59.313949999999998] }, "$maxDistance" : 500.0 } } }] }} var successfulFindResult = collection.Find(successfulFilterDefintionAsString).ToList(); |
Console.WriteLine(successfulFindResult[0]["name"]); //A Console.ReadKey(); |
}
|
}
|
}
|
|
The attached image describe the geometry objects used in this example.
