Haywire
Haywire

Reputation: 878

$and with $nearSphere in mongodb

I have a collection having from and to point locations. Now I wish to find documents which have both, to and from locations nearby the given source and destinations.

Here's the setup:

collection: db.t2.find():

{ 
    "_id" : ObjectId("5..4"), 
    "uid" : "sdrr", 
    "valid_upto": 122334, 
    "loc" : { 
        "from" : { 
            "type" : "Point", 
            "coordinates" : [  77.206672,  28.543347 ] 
        },
        "to" : { 
            "type" : "Point",
            "coordinates" : [  77.1997687,  28.5567278 ] 
        }
    }
}

Indices: db.t2.getIndices():

{
    "v" : 1,
    "name" : "_id_",
    "key" : {
        "_id" : 1
    },
    "ns" : "mydb.t2"
},
{
    "v" : 1,
    "name" : "uid_1_loc.from_2dsphere_loc.to_2dsphere_valid_upto_1",
    "key" : {
        "uid" : 1,
        "loc.from" : "2dsphere",
        "loc.to" : "2dsphere",
        "valid_upto" : 1
    },
    "ns" : "mydb.t2"
}

Single queries for either to or from work good with the current settings give nice results. However, when I use to and from together in a single query with $and clause:

db.t2.find({
    "$and" : [  
        {   
            "loc.from" : { 
                "$nearSphere" : [ 77.5454589,28.4621213 ], 
                "$maxDistance" : 0.18 
            }
        },
        {
            "loc.to" : {    
                "$nearSphere" : [ 77.206672, 28.543347 ], 
                "$maxDistance" : 0.18 
            }
        }
    ]
})

it throws the following error:

error: {
"$err" : "can't find any special indices: 2d (needs index), 2dsphere (needs index), for: { $and: [ { loc.from: { $nearSphere: [ 77.5454589, 28.4621213 ], $maxDistance: 0.18 } }, { loc.to: { $nearSphere: [ 77.206672, 28.543347 ], $maxDistance: 0.18 } } ] }",
"code" : 13038
}

I suppose the data has been indexed as evident from getIndices(), but still its unable to find indices! Where is the problem then and how can I fix it to have effect of a $and-ed operation?

Upvotes: 0

Views: 974

Answers (2)

Neil Lunn
Neil Lunn

Reputation: 151112

The error appears to be present from a MongoDB 2.4 version where there indeed was a bug that would not allow a $near type of query within and $and operation that accessed another field.

But your particular problem here is that you just cannot do this.

The code and comments to test this can be vied on GitHub but essentially:

    // There can only be one NEAR.  If there is a NEAR, it must be either the root or the root
    // must be an AND and its child must be a NEAR.
    size_t numGeoNear = countNodes(root, MatchExpression::GEO_NEAR);
    if (numGeoNear > 1) {
        return Status(ErrorCodes::BadValue, "Too many geoNear expressions");
    }

So that is an error that would be emitted from MongoDB 2.6 you tried to do this.

A brief look at all the surrounding code within the method will show you that "geo" queries are not alone in this and the other "special" index type of "text" is included in the same rules.

Part of the reason for this is the $meta "scoring" that is required, as in this case is $maxDistance. There really is no valid way to combine or discern which value would actually apply in combined results such as this.

On a bit more of a technical note, the other issue is with being able to "intersect" indexes in a query such as this. The required fuzzy matching makes this a very different prospect to something like the basic "Btree" index intersection.

For now at least, your best approach is to perform each query by itself and manually "union/intersect" your results in code, with of course your own tagging as to which results are for your origin and which are for your destination.

Upvotes: 2

John Petrone
John Petrone

Reputation: 27487

This was a known issue in version 2.4 and prior of MongoDB, fixed in version 2.5.5:

https://jira.mongodb.org/browse/SERVER-4572

Core ServerSERVER-4572 Geospatial index cannot be used in $and criteria of a query?

Should be fixed as of 2.6 - if you're running 2.4 or previous I'd upgrade, if you're running 2.6.X I'd report it as a bug.

Upvotes: 0

Related Questions