geoNear aggregation query parameter with text search

2,118 views
Skip to first unread message

Devin Smith

unread,
Jun 2, 2014, 12:35:33 PM6/2/14
to mongod...@googlegroups.com
I would really like to do something like this:

db.events.aggregate({$geoNear:{near:[<longitude>, <latitude>], distanceField:"distance", query:{$text:{$search:<my search here>}}}})

I'm getting:

uncaught exception: aggregate failed: {
"errmsg" : "exception: geoNear command failed: { ok: 0.0, errmsg: \"Can't parse filter / create query\" }",
"code" : 16604,
"ok" : 0
}

I have successfully used the query on simple fields, but it won't work with text.

I know that there are general issues with combining special index types such as geo + text... for my use case though, I imagine that the geo search will really filter down my dataset, and after that point I don't care how fast the text filtering is.

My alternative that seems to work is:

db.events.find({loc:{$geoWithin:{$center: [<longitude>, <latitude>], <maxDistance>]}}, $text:{$search:<my search here>}}) 

The difference with this second query though is that I have to provide a <maxDistance>, I don't get the distance computed like I do with the geoNear's distanceField parameter... and thus I can't sort (and then limit) based on the distance.

Any help would be much appreciated!

Devin Smith

unread,
Jun 2, 2014, 1:52:05 PM6/2/14
to mongod...@googlegroups.com
Also, in the find workaround, it is not taking advantage of the geospatial index (which I think will be much more helpful than the text index)

Devin Smith

unread,
Jun 4, 2014, 4:20:24 PM6/4/14
to mongod...@googlegroups.com
Any ideas?

José Antonio Sánchez Ortiz

unread,
Jun 5, 2014, 6:01:41 AM6/5/14
to mongod...@googlegroups.com
Hello Devin.

The MongoDB documentation states that The $match stage that includes a $text must be the first stage in the pipeline. And in other place states that you can only use $geoNear as the first stage of a pipeline. Then, only one of the previous could be the first stage. It is not exactly the same situation you have, but it is quite similar. 

In your find workaround you can hint the geospatial index with db.events.find( ... ).hint( { key pattern of geospatial index } ).

By the way, ¿could you change the text search with a normal search? Lets say, you only have to match equality ( type : "food" ) and you haven´t things like type : "food -beverage". In case you could use a normal search, you could use a compound index with geospatial and the other field, and you could keep with aggregation.

José

Devin Smith

unread,
Jun 9, 2014, 12:59:15 PM6/9/14
to mongod...@googlegroups.com
I forgot to mention that I also tried to hint that I would like the geo index to be used (over the text index). Unfortunately, it returns the error:

error: {
"$err" : "Can't canonicalize query: BadValue text and hint not allowed in same query",
"code" : 17287
}

:O

Unfortunately, my text search isn't a simple equality test.

Pankaj Aggarwal

unread,
Jul 13, 2014, 8:33:17 PM7/13/14
to mongod...@googlegroups.com
Hello Devin

I'm in a similar situation. I need a single query doing geospatial and text search.

Have you found any solution to it yet ?

If you have please do provide us the solution

Will Berkeley

unread,
Jul 17, 2014, 12:13:27 PM7/17/14
to mongod...@googlegroups.com
Hi Pankaj. From the text indexes docs,

A compound index can include a text index key in combination with ascending/descending index keys. However, these compound indexes have the following restrictions:
A compound text index cannot include any other special index types, such as multi-key or geospatial index fields.

so you cannot use both a text index and a geospatial index in one find query. As stated further up in the thread, you also cannot use both a text index and a geospatial index in the aggregation framework as both must be part of the first stage of the pipeline. However, the geoWithin operator, which computes if a point, line, or shape lies within another defined shape, does not require a geospatial index, so you could use that to do a find query combining geospatial and text. I've included an example below:

> db.txtgeo.insert({"text":"the quick brown fox jumps over the lazy dog", loc: [34.33, 86.44]})

> db.txtgeo.ensureIndex({text:"text"})

> db.txtgeo.find({$text:{$search:"fox"}})
{ "_id" : ObjectId("53c7f37bff6430e9d1baec50"), "text" : "the quick brown fox jumps over the lazy dog", "loc" : [ 34.33, 86.44 ] }

> db.txtgeo.find({$text:{$search:"fox"}, loc: {$geoWithin : {$center: [[33.22, 84.12], 200]}}})
{ "_id" : ObjectId("53c7f37bff6430e9d1baec50"), "text" : "the quick brown fox jumps over the lazy dog", "loc" : [ 34.33, 86.44 ] }
 
db
.txtgeo.find({$text:{$search:"fox"}, loc: {$geoWithin : {$center: [[33.22, 84.12], .02]}}})
(no results)

-Will
Reply all
Reply to author
Forward
0 new messages