你不能用简单的.find() 语句来做那种查询(不是双关语)。您所要求的涉及“加权”,即对值应用“计算的优先级。
任何带有“计算”的东西基本上都是以编程方式应用的条件,并且此处“排序”的特定断言排除了“JavaScript 运行器”选项,如 mapReduce,并简单地离开聚合框架或结果的其他处理。
对于聚合框架方法,您需要 $project 根据条件为每个匹配的文档计算“权重”:
db.collection.aggregate([
// Same match conditions to filter
{ "$match": { "$or": [{ "family": 1, }, { "category": 2 }] } },
// Assign the "weight" based on conditions
{ "$project": {
"name": 1,
"family": 1,
"weight": {
"$add": [
{ "$cond": {
"if": { "$eq": [ "$family", 1 ] },
"then": 1,
"else": 0
}},
{ "$cond": {
"if": { "$eq": [ "$category", 2 ] },
"then": 1,
"else": 0
}}
]
}
}},
// Then sort "descending" with highest "weight" on top
{ "$sort": { "weight": -1 } }
])
基本上,您使用$cond 来评估返回文档实际上具有满足您条件的数据的条件,因为在选择中存在的任一字段都是有效响应。在条件存在的地方,我们分配一个值,在不存在的地方,值是0。
当“两种”条件都存在时,$add 操作会将总和合并到权重中。所以这里只满足一个条件的文档有一个1,对于这两个条件它们都有2。如果您希望例如“家庭”有更大的偏好,那么您将在条件中分配2,从而为您留下可能的文档分数:
-
3 :适用于和家庭
类别
-
2:仅限家庭
-
1:仅适用于类别
您可以在 MongoDB 3.4 或更高版本中使用 $addFields 管道运算符缩短 $project 的语法,这在您想要返回“大量”其他文档属性而无需列出时最有用他们都在$project。
除此之外,数据库服务不允许对“排序”进行“计算”。这被认为是“操纵”,这是聚合框架的目的。
虽然您可以通过在客户端代码中对结果集进行后处理来执行相同类型的“加权”,但这里的问题当然是您希望“限制”结果以在“分页”等操作中返回。这就是在服务器上运行操作发挥作用的地方,也是您为此使用聚合框架的原因。