Mongo incorrectly sorting on array field?

不问归期 提交于 2019-12-11 11:19:08

问题


I'm trying to filter on an array field which unfortunately doesn't seem to be working correctly. Everything I've read suggests that this should work, and the sort is doing something, just not what I expected and I can't explain it.

What I'm trying to achieve is sorting on an array sub-field. I've managed to achieve most of this using the positional operator but I can't work out what the sort is doing.

db.getCollection('boards')
  .find({ "lastVisited.user": "AAA" }, { name: 1, "lastVisited.$" : 1 })
  .sort({ "lastVisited.0.timestamp": 1 });

This results in the following output

/* 1 */
{
    "_id" : ObjectId("5b642d2cac2f544b1d48d09a"),
    "lastVisited" : [ 
        {
            "user" : "AAA",
            "timestamp" : ISODate("2018-08-18T00:00:00.000Z")
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("5b6845245e102f3844d2181b"),
    "lastVisited" : [ 
        {
            "user" : "AAA",
            "timestamp" : ISODate("2018-08-16T00:00:00.000Z")
        }
    ]
}

/* 3 */
{
    "_id" : ObjectId("5b6842095e102f3844d2181a"),
    "lastVisited" : [ 
        {
            "user" : "AAA",
            "timestamp" : ISODate("2018-08-19T00:00:00.000Z")
        }
    ]
}

The thing to note here is that the dates are ordered 18th then 19th then 16th which makes no sense! Can anyone explain this?

These are the documents that I've used:

/* 1 */
{
    "_id" : ObjectId("5b642d2cac2f544b1d48d09a"),
    "lastVisited" : [ 
        {
            "user" : "BBB",
            "timestamp" : ISODate("2018-08-04T00:00:00.000Z")
        }, 
        {
            "user" : "AAA",
            "timestamp" : ISODate("2018-08-18T00:00:00.000Z")
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("5b6842095e102f3844d2181a"),
    "lastVisited" : [ 
        {
            "user" : "AAA",
            "timestamp" : ISODate("2018-08-19T00:00:00.000Z")
        }
    ]
}

/* 3 */
{
    "_id" : ObjectId("5b6845245e102f3844d2181b"),
    "lastVisited" : [ 
        {
            "user" : "AAA",
            "timestamp" : ISODate("2018-08-16T00:00:00.000Z")
        }
    ]
}

回答1:


Unfortunately you can't do this currently in Mongo, as it still uses the full document (not just the projected part) to sort on. So you'll need to use the aggregation framework instead. See an open issue https://jira.mongodb.org/browse/SERVER-4451

Here's an example with aggregation, as you want your sort to happen on matched elements

db.getCollection('stack1').aggregate([
// Initial document match (uses index, if a suitable one is available)
{ $match: 
    { "lastVisited.user": "AAA" }
},
{ "$unwind":"$lastVisited"},
{ $match:{
    "lastVisited.user": "AAA"
}},
{ "$sort": { "lastVisited.timestamp": 1 } }    

])


来源:https://stackoverflow.com/questions/51711544/mongo-incorrectly-sorting-on-array-field

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!