简体   繁体   中英

How to sort inner array and match elements in mongoose

So I am trying to do a semi-complicated query in mongoose. It is as follows:

Event.findOne({ users: { $elemMatch: { user: someUserId, going: 1 }, sort: {createTime: -1} } }

Basically what I would like to do is find a single Event that has a user in its user array that matches an Id and is attending. I have multiple user records for each user in the user array so I want to find the most recent one, to do this I would like to sort the user array by createTime. This is where the error is coming in and it just returns undefined . It works just fine when I don't include the sort function, is there any way to include that?

Here is what my Event object looks like:

{ 
  _id: 1,
  endTime: 1429060173865,
  createTime: 1429051773902,
  startTime: 1429052973865,
  description: 'some desc',
  creator: 2,
  users:
   [ { user: 1,
       status: 1,
       going: 1,
       createTime: 1429051773749,
       _id: 552d997d8e923847306e2c21 },
     { user: 1,
       status: 1,
       going: 1,
       createTime: 1429051773922,
       _id: 552d997d8e923847306e2c25 },
     { user: 1,
       status: 9,
       going: 0,
       createTime: 1429051773942,
       _id: 552d997d8e923847306e2c26 } ],
  destroyed: 0 }

Is there any way to make this query entirely in mongoose?

As part of find, MongoDB can't sort an array field of a document. You could define a virtual of Mongoose to return the array in sorted order. You could also maintain the array in sorted order, as shown below:

> db.test.drop()
// note: not in order when inserted
> db.test.insert({ "_id" : 0, "users" : [
    { "user" : 1, "going" : 1, "created" : 22 },
    { "user" : 2, "going" : 1, "created" : 775 },
    { "user" : 1, "going" : 1, "created" : 6432 }
] })
// insert user to array and sort as part of update
> db.test.update({ "_id" : 0 },
    { "$push" : { 
        "users" : {
            "$each" : [{ "user" : 2, "going" : 1, "created" : 5532 }],
            "$sort" : { "created" : -1 }
        }
    } })
> > db.test.findOne()
{
    "_id" : 0,
    "users" : [
        { "user" : 1, "going" : 1, "created" : 6432 },
        { "user" : 2, "going" : 1, "created" : 5532 },
        { "user" : 2, "going" : 1, "created" : 775 },
        { "user" : 1, "going" : 1, "created" : 22 }
    ]
}

That way, when you perform your find query, the arrays in the matching documents will already be in the desired order.

Your query is not correctly written. In order to sort you should write it in third argument of find:

Event.findOne(
     { users: 
           { $elemMatch: { user: someUserId, going: 1 }}
     },
     null,
     { 
         sort: {createTime: -1} 
     },
     function(err, event) {
         //your event here
     });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM