MongoDB排序,如果值等于某物



有没有办法在Mongodb ->字段中进行排序,如果字段等于某个值?

例如:

像这样的东西

db.users.aggregate(
[
{ $sort : { username : 'john' ? -1 : 1, posts: 1 } }
]
)

如果我想排序,让我们说username字段..
如果用户名等于"john",则在结果中将用户放在首位

不可能

如果MongoDB

无法通过索引扫描获取排序顺序,则MongoDB使用top-k排序算法。此算法缓冲基础索引或集合访问到目前为止看到的前k个结果(或最后一个,具体取决于排序顺序(。如果在任何时候这些 k 结果的内存占用超过 32 MB,则查询将失败。

https://docs.mongodb.com/manual/reference/method/cursor.sort/#limit-results

我们不能覆盖排序算法,但我们可以做一些棘手的解决方案。

解决方案 1.(性能良好(

添加额外字段(即order(。对于"username" : "john"设置0值,对于其他用户名,设置1值。创建新索引 {顺序:1, 用户名:1, 帖子:1}

现在,当您按索引字段排序时,John将排在第一位。

解决方案 2(性能不佳(

我们做同样的事情,但动态的。

db.users.aggregate([
{
$addFields: {
order: {
$cond: [
{
$eq: [
"$username",
"john"
]
},
0,
1
]
}
}
},
{
$sort: {
order: 1,
username: 1,
posts: 1
}
}
])

蒙戈游乐场

我想你正在寻找这样的东西。

输入文档:

{ "username" : "jack", "posts" : "hello world" }
{ "username" : "chris", "posts" : "java programming" }
{ "username" : "krish", "posts" : "mongo mongo" }
{ "username" : "john", "posts" : "rock-n-roll" }

查询:

db.users.aggregate( [
{ 
$facet: {
input_user: [
{ $match: { username: INPUT_NAME } }
],
other: [
{ $match: { username: { $ne: INPUT_NAME } } },
{ $sort: { username: 1 } }
]
} 
},
{
$project: { result: { $concatArrays: [ "$input_user", "$other" ] } }
}
] )

输出:

INPUT_NAME = 'john'时,则username的顺序为: "约翰"、"克里斯"、"杰克"和"克里希"。

而且,当INPUT_NAME = 'some other'时,它是:"克里斯","杰克","约翰"和"克里什"。



注意:

上述解决方案适用于小型集合,但不会在username+posts字段上使用定义的索引 - 这可能会导致较大集合的性能降低。

因此,一个选项是使用两个查询并合并结果。在这种情况下,查询过滤器以及排序操作将使用这样定义的索引:{ username: 1, posts: 1 } }

例如:

let result_1 = db.users.find( { username: { $ne: INPUT_NAME } } ).sort( { username: 1, posts: 1 } ).toArray()
let result = db.users.find( { username: INPUT_NAME } ).sort( { username: 1, posts: 1 } ).toArray().concat(result_1)

查询可以是聚合,其优点是使用更多内存进行排序操作。索引将用于匹配和排序操作。

  • $sort和内存 限制(聚合(。
  • $sort和内存 限制(查找.光标(

最新更新