user3730696
user3730696

Reputation:

Mongo search by last inserted items

I have a documents structure like this

{
  _id: 1,
  userId: 10,
  tags:   ['a', 'b', 'c'],
  created: '2014-06-01'
},

{
  _id: 2,
  userId: 10,
  tags:   [],
  created: '2014-06-05'
}

{
  _id: 3,
  userId: 11,
  tags:   ['a', 'b', 'c'],
  created: '2014-05-29'
}

And I want to get result (search by tags) like this (search only by last inserted items).If last inserted item does not have tag it should not be displayed as a result of

{
    _id: 3,
   userId: 11,
   tags:   ['a', 'b', 'c'],
   created: '2014-06-02'
}

So, I tried to do it with the next query

db.users.find({tags: 'a'}).sort({created: -1})

and result looks like this

{
   _id: 3,
   userId: 11,
   tags:   ['a', 'b', 'c'],
   created: '2014-06-02'
}

{
  _id: 1,
  userId: 10,
  tags:   ['a', 'b', 'c'],
  created: '2014-06-01'
}

but the result is not one that I expected... because last item does not have any tags

Upvotes: 0

Views: 75

Answers (2)

John Petrone
John Petrone

Reputation: 27515

So if I understand you correctly, you would like to search for the presence of a specific tag within the tags array but only searching within the very last document according to "created".

So two things you need to do:

  1. Fix your "created" field. It's stored as a string and that won't do, as you can't easily compare dates stored as strings, so sorting won't work. So you'll need to fix that. Please check out the documentation of BSON Date types and also look at the documentation for whatever language/driver you are using. http://docs.mongodb.org/manual/reference/bson-types/#document-bson-type-date
  2. Use the aggregation framework. You can use the aggregation framework to perform this type of analysis. I've included sample code below, assuming your sample schema has been corrected with the proper Date format:

    { _id: 1, userId: 10, tags: ['a', 'b', 'c'], created: ISODate("2014-06-01T10:50:42.389Z") }

    { _id: 2, userId: 10, tags: [], created: ISODate("2014-06-05T12:30:48.389Z") }

    { _id: 3, userId: 11, tags: ['a', 'b', 'c'], created: ISODate("2014-05-05T02:12:09.389Z") }

You can then run the following aggregation pipeline command:

db.collectionname.aggregate([
                     {$sort:{created:-1}}, 
                     {$limit:1}, 
                     {$match:{tags:"a"}}
                     ])

This will match nothing as the last document inserted by created does not have "a" in the tags array. If you then add a new document:

{
  _id: 4,
  userId: 11,
  tags:   ['a', 'c'],
  created: ISODate("2014-06-09T02:12:09.389Z")
}

which is now the latest created and has "a" in tags and run this command you get:

{ 
  "_id" : 4, 
  "userId" : 11, 
  "tags" : [ "a", "c" ], 
  "created" : ISODate("2014-06-09T02:12:09.389Z") 
}

Which is I believe the desired result. More on the aggregation framework here:

http://docs.mongodb.org/manual/core/aggregation-introduction/

Upvotes: 1

displayName
displayName

Reputation: 14399

It is because the field created is not a valid Date type field in MongoDB.

You need to store the values in that field properly. One way could be to insert values like:

created : ObjectId().getTimestamp()

Now created will have a valid MongoDB Date value. To sort them in reverse chronological order all you've got to run is:

db.collection.find().sort({'created' : -1});

You can put something in find() to search for your specific documents. You did put a search on tags in your question. I've skipped it though. You have got the idea now for sure...

Upvotes: 0

Related Questions