Reputation: 11
Using mongoose, I want to search for subdocuments that have a certain property and return the most recent one.
// the relevant part of the user schema
id: String,
__history__: {
reply: []
}
// the components of a 'reply' (not defined by a schema)
id: String,
createdAt: Date,
props {
tipID: String
}
Given a specific user id
, I want to search their reply[]
s for replies that have a tipID
in their props
. I then want to return the tipID
for the reply
that has the most recent createdAt
.
I'm new to - well - coding in general. Would love any pointers on how best to tackle this.
Upvotes: 1
Views: 547
Reputation: 11
Because $elemMatch was returning an error (I think because reply wasn't a proper schema defined doc), I got the following to work instead.
User.findOne("_id": user._id}, function (err, doc) {
var replies = doc.__history__.reply;
for ( var i = 0; i < replies.length; i++ ) {
if (replies[i].props.hasOwnProperty("tipId")) {
// do something
break; // stop because i only wanted the first hit
}
}
Note: I didn't have to worry about sorting by time because __history__.reply
items were already ordered by most recent first.
Upvotes: 0
Reputation: 1778
If you're only finding one document, then organize the replies something like this..
// find your doc by ID
user.findOne({ id: id }, function(err, doc) {
// sort replies by createdAt date
var replies = _.sortBy(doc.reply, function(reply) {
return reply.createdAt.getTime(); // convert to seconds from jan 1, 1970
});
return replies[0].props.tipId;
})
Upvotes: 1
Reputation: 832
This is a duplicate question of Mongoose - finding subdocuments by criteria
For your specific question, the trick with mongoose subdocuments is twofold:
a) avoid nesting within subdocuments if you can, i.e. do not nest your attributes within propId
rather put those attributes straight into the reply, whatever they may be.
b) use $elemMatch
as suggested in the duplicate answer I quoted above. This will make sure that mongoDb finds the right documents, since mongoDb recognises {a:1,b:2}
and {b:2,a:1}
as two different subdocuments.
Upvotes: 1