[CSHARP-1330] MongoDb Database query for Geo Near using c# Created: 22/Jun/15  Updated: 05/Apr/19  Resolved: 22/Jun/15

Status: Closed
Project: C# Driver
Component/s: API
Affects Version/s: 2.0.1
Fix Version/s: None

Type: Task Priority: Major - P3
Reporter: Arvind Chary Assignee: Unassigned
Resolution: Incomplete Votes: 0
Labels: query, question
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Windows


Attachments: PNG File 2.png    

 Description   

I am using Mongo CSharpDriver-2.0.0 version and IMongoCollection Async in my application. My data collection looks as shown in the figure attached(2.png).
Here I want to perform a Search operation on Venue Details, basically we will give a pair of Latitude and Longitude and it should return a list of Records that are with in the distance of 4000 meters from provided Latitude and Longitude.
To implement above functionality I am using the below code: This code works fine when I pass a single category.

IMongoCollection<BusinessDeal> BusinessCollection;
BusinessCollection = _database.GetCollection<BusinessDeal>("BusinessDeals2");

double? rangeInMeters = null;
if (rangeInMeters == null)

{ rangeInMeters = 3000; }

//add index for venue.location and category
var keyBuilder = Builders<BusinessDeal>.IndexKeys;
keyBuilder.Geo2DSphere(x => x.Venuedetails.Select(y => y.Location)).Ascending(x => x.Categories.Select(y => y.Id));
keyBuilder.Geo2DSphere(x => x.Venuedetails.Select(y => y.Location)).Ascending(x => x.Accessgroups.Select(y => y.Id));

BsonDocument geoPoint = new BsonDocument
{

{"type","Point"}

,
{"coordinates",new BsonArray(new double[]{-84.289156, 34.289156})}
};

BsonDocument geoNearOptions = new BsonDocument
{

{"spherical", true}

,

{"limit", 300}

,should we do a filter first?

{"maxDistance", rangeInMeters}

,

{"near",geoPoint}

,

{"distanceField","dist"}

};

var stage = new BsonDocumentPipelineStageDefinition<BusinessDeal, BusinessDeal>(new BsonDocument {

{ "$geoNear", geoNearOptions }

});

var colAggregate = BusinessCollection.Aggregate().AppendStage(stage);
var result = BusinessCollection.Aggregate().ToListAsync();
_businessDealsList = result.Result;

The above code is returning all the records that are in the Collection. But there are only 2 records that are 4000 meters of distance. My records are as follows:
Latitude1 Longitude1 Latitude2 Longitude2 Distance from Origin in Meters
Record1 -84.289156 34.289156 -84.288357 34.068686 2414.016
Record2 -84.289156 34.289156 -84.299477 34.069886 2735.8848
Record3 -84.289156 34.289156 -84.299477 34.690986 4667.0976

When I run or Debug the code, it returns all the three records. But it should return only 2 records. Please review the code that I have written and help where I am going wrong. Thanks in advance for your help and support.



 Comments   
Comment by Craig Wilson [ 22/Jun/15 ]

All I can tell you is that the exception seems pretty clear: 'near' field must be point. Presumably, the format you are providing to the near field is incorrect and is not recognized as a point.

I'm going to suggest continuing this discussion in the google groups thread you've already started. More eyes on the problem will help solve it faster: https://groups.google.com/forum/?pli=1#!topic/mongodb-user/mXKzOAhJ9No

Craig

Comment by Arvind Chary [ 22/Jun/15 ]

I have updated my code as follows:

IMongoCollection<BusinessDeal> BusinessCollection;
BusinessCollection = _database.GetCollection<BusinessDeal>("BusinessDeals2");

double? rangeInMeters = null;
if (rangeInMeters == null)

{ rangeInMeters = 3000; }

try
{
//add index for venue.location and category
var keyBuilder = Builders<BusinessDeal>.IndexKeys;
keyBuilder.Geo2DSphere("Venuedetails.geosonLoc.coordinates").Ascending("Categories._id");

keyBuilder.Geo2DSphere(x => x.Venuedetails.Select(y => y.Location)).Ascending(x => x.Categories.Select(y => y.Id));
keyBuilder.Geo2DSphere(x => x.Venuedetails.Select(y => y.Location)).Ascending(x => x.Accessgroups.Select(y => y.Id));

BusinessCollection.Indexes.CreateOneAsync(Builders<BusinessDeal>.IndexKeys.Geo2D("Venuedetails.geosonLoc.coordinates"));

var indexes = BusinessCollection.Indexes.ListAsync();

BsonDocument geoPoint = new BsonDocument
{

{"type","Point"}

,
{"coordinates",new BsonArray(new double[]

{ 29.764254, -95.367403 }

)}
};

BsonDocument geoNearOptions = new BsonDocument
{

{"spherical", true}

,

{"limit", 300}

, //need to test to see what limit is appropriate, should we do a filter first?

{"maxDistance", rangeInMeters}

,

{"near", geoPoint}

,

{"distanceField", "distinct"}

};

//MongoDB requires $geoNear as the first stage of a pipeline.
var stage = new BsonDocumentPipelineStageDefinition<BusinessDeal, BusinessDeal>(new BsonDocument {

{ "$geoNear", geoNearOptions }

});

var colAggregate = BusinessCollection.Aggregate().AppendStage(stage);
//var filter = (dynamic)null;

result = BusinessCollection.Aggregate().AppendStage(stage).ToListAsync();
_businessDealsList = result.Result;
}
catch (Exception ex)

{ string str = (ex.InnerException).Message; }

When I execute my code I am getting following error message: "Message=Command aggregate failed: exception: geoNear command failed:

{ errmsg: "exception: 'near' field must be point", code: 17304, ok: 0.0 }

."

Can you help me why I am getting this error. Thanks in advance for your help and support.

Comment by Craig Wilson [ 22/Jun/15 ]

Hi Arvind,

This error is coming back from the server and is likely related to a missing index. For instance, in your code, the only index you are creating is this: BusinessCollection.Indexes.CreateOneAsync(Builders<BusinessDeal>.IndexKeys.Ascending("Venuedetails.geosonLoc.coordinates"));. However, that isn't a geo index. You previously had some code about a geo index that is unused.

Craig

Comment by Arvind Chary [ 22/Jun/15 ]

Hello Craig,
Thanks, for your quick response. I have changed my code as follows:
IMongoCollection<BusinessDeal> BusinessCollection;
BusinessCollection = _database.GetCollection<BusinessDeal>("BusinessDeals2");

double? rangeInMeters = null;
if (rangeInMeters == null)

{ rangeInMeters = 3000; }

//add index for venue.location and category
var keyBuilder = Builders<BusinessDeal>.IndexKeys;
keyBuilder.Geo2DSphere("Venuedetails.geosonLoc.coordinates").Ascending("Categories._id");

BusinessCollection.Indexes.CreateOneAsync(Builders<BusinessDeal>.IndexKeys.Ascending("Venuedetails.geosonLoc.coordinates"));
var indexes = BusinessCollection.Indexes.ListAsync();

BsonDocument geoPoint = new BsonDocument
{

{"type","Point"}

,
{"coordinates",new BsonArray(new double[]{-84.289156, 34.289156})}
};

BsonDocument geoNearOptions = new BsonDocument
{

{"spherical", true}

,

{"limit", 300}

, //need to test to see what limit is appropriate, should we do a filter first?

{"maxDistance", rangeInMeters}

,

{"near", geoPoint}

,

{"distanceField", "distinct"}

};

//MongoDB requires $geoNear as the first stage of a pipeline.
var stage = new BsonDocumentPipelineStageDefinition<BusinessDeal, BusinessDeal>(new BsonDocument {

{ "$geoNear", geoNearOptions }

});

var colAggregate = BusinessCollection.Aggregate().AppendStage(stage);
//var filter = (dynamic)null;

var result = BusinessCollection.Aggregate().AppendStage(stage).ToListAsync();
_businessDealsList = result.Result;

When execute the above code I am getting error message as "Message=Command aggregate failed: exception: geoNear command failed:

{ ok: 0.0, errmsg: "can't get query executor" }

.".

Can you help me why I am getting this error. Thanks in advance for your help and support.

Comment by Craig Wilson [ 22/Jun/15 ]

Hi Arvind,

In the future, please use the discussion forum or stackoverflow.com for questions like this. Our ticket system is reserved for questions and feature requests.

Your problem is this:

var colAggregate = BusinessCollection.Aggregate().AppendStage(stage);
var result = BusinessCollection.Aggregate().ToListAsync();
_businessDealsList = result.Result;

You never run "colAggregate". You run, instead, an empty pipeline.

Craig

Generated at Wed Feb 07 21:39:17 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.