问题
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