有没有办法在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和内存 限制(查找.光标(