2014년 11월 30일 일요일

Mongo query bug ?

I run a very simple query: db.tasks.find({name: 'test', author:ObjectId("52120773bfb5ccce7500000a")})
which returns no document while there is a document that matches the query.
The same document is returned if I do:
db.tasks.find({author:ObjectId("52120773bfb5ccce7500000a")})
or
db.tasks.find({name: 'test-trash-3', author:ObjectId("52120773bfb5ccce7500000a")})
but if I try to combine both criterias it is empty, most objects in the collection dont' have this issue, they're all created using mongoose.js, but only a small minority have the issue.
Mongo version is 2.4.9 mongoose is the latest one.
Any suggestion on how to proceed with troubleshooting (or pointer to a known bug) would be awesome :)



You mention that this query succeeds and returns:

db.tasks.find({name: 'test-trash-3', author:ObjectId("52120773bfb5ccce7500000a")})

And this one fails:

db.tasks.find({name: 'test', author:ObjectId("52120773bfb5ccce7500000a")})

This may be an issue with how you have described it, but it seems to me that the issue is that the name field in the second query is the problem, that is that a document with the field {name: 'test'} and the author you specify basically does not exist, however a document with {name: 'test-trash-3'} and the author you specify does.


The criteria must both match remember, this is a logical AND by default, not a logical OR.



sorry for the confusion, db.tasks.find({name: 'test-trash-3', author:ObjectId("52120773bfb5ccce7500000a")}) returns empty while
db.tasks.find({name: 'test-trash-3'}) and  db.tasks.find({author:ObjectId("52120773bfb5ccce7500000a")}) return the same document

this sounds like a mongo bug to me.



Can you do an explain on each of the three queries and post the results here?  The output of db.tasks.getIndexes() would be helpful also, and I would really like to see the full documents being returned (specifically the _id fields if the whole document is not possible).  I suspect it has to do with index selection or similar, because if there was a bug this basic we would have thousands of people seeing it constantly - it's one of the most fundamental pieces of the query engine.



Would you please include the document that's being returned to these two queries?

db.tasks.find({name: 'test-trash-3'})
db.tasks.find({author:ObjectId("52120773bfb5ccce7500000a")}) 

By the way, you mentioned mongoose - are you making these queries via mongoose or via the mongo shell?

Do you happen to have any indexes on this collection?



yes, I agree with you, here's a sample copy paste of two queries:
> db.tasks.find({name:"newFieldNoticePas"}, {author:1})
{ "_id" : ObjectId("5461320d4e84ee3c48f28ee7"), "author" : ObjectId("524ad49e2718e1645a000106") }
> db.tasks.find({name:"newFieldNoticePas", "author" : ObjectId("524ad49e2718e1645a000106")}, {author:1})
>
obviously the second query should return the same object.

So I looked at the indexes as you suggested, and there were a few I don't use anymore, which I deleted and this fixed the issue!
> db.tasks.find({name:"newFieldNoticePas", "author" : ObjectId("524ad49e2718e1645a000106")}, {author:1})

{ "_id" : ObjectId("5461320d4e84ee3c48f28ee7"), "author" : ObjectId("524ad49e2718e1645a000106") }
These are the indexes I deleted:
> db.tasks.dropIndex('views_1')
> db.tasks.dropIndex('uses_1')
> db.tasks.dropIndex('description_1')
> db.tasks.dropIndex('entitlements_1')
> db.tasks.dropIndex('author_1_name_1_description_1_labels_1_updated_at_-1')
> db.tasks.dropIndex('author_1_entitlements_1_name_1_description_1_uses_-1')
> db.tasks.dropIndex('author_1_entitlements_1_name_1_description_1_updated_at_-1')
Could it be that this index:
> db.tasks.dropIndex('author_1_name_1_description_1_labels_1_updated_at_-1')

was incomplete and used for the second query ? If so how can one prevent this ? 

PS: yes I use mongoose, but as I could replicate on the mongo shell, I thought it best to use the mongo shell examples.



Well, now that you dropped the possibly corrupt index it's not going to be possible to verify whether or not it was corrupt!  :)

But if you happen to have a backup of the DB from before you dropped that index, you can restore it and run db.collectionName.validate(true) on it and see if any corruption is reported on it.  It's certainly possible that something was not-quite-right with that index (and that index is what would have been selected for the query).


댓글 없음:

댓글 쓰기