mongodb:具有最大匹配目标数的文档

mongodb:具有最大匹配目标数的文档,mongodb,mongoose,mongodb-query,aggregation-framework,Mongodb,Mongoose,Mongodb Query,Aggregation Framework,我需要帮助来解决以下问题。我的收藏有一个“目标”字段 每个用户可以有0个或多个目标 当我运行查询时,我希望检索具有最大匹配目标数的文档 例: 您似乎要求返回满足最多条件的文档,可能不是所有条件。基本过程是一个$或查询,以返回可以匹配任一条件的文档。然后,您基本上需要一个语句来计算文档中满足了“多少条件”,并返回匹配最多的条件 因此,这里的组合是一个语句,它使用的初始结果用于计算结果,然后对结果进行排序: //初始目标对象 var userTarget={ “集群”:“01”, “环境”:“DC”

我需要帮助来解决以下问题。我的收藏有一个“目标”字段

每个用户可以有0个或多个目标

当我运行查询时,我希望检索具有最大匹配目标数的文档

例:


您似乎要求返回满足最多条件的文档,可能不是所有条件。基本过程是一个
$或
查询,以返回可以匹配任一条件的文档。然后,您基本上需要一个语句来计算文档中满足了“多少条件”,并返回匹配最多的条件

因此,这里的组合是一个语句,它使用的初始结果用于计算结果,然后对结果进行排序:

//初始目标对象
var userTarget={
“集群”:“01”,
“环境”:“DC”,
“核心”:“PO”
};
//转换成美元或条件
//与计算条件相匹配
变量或条件=[],
scoreCondition=[]
key(userTarget).forEach(function(key){
var query={},
cond={“$cond”:[{“$eq”:[“$target.”+key,userTarget[key]]},1,0]};
查询[“target.+key]=userTarget[key];
orCondition.push(查询);
计分条件推(秒);
});
//运行聚合
模型集料(
[
//符合条件
{“$match”:{“$or”:或条件},
//根据匹配字段计算“分数”
{“$project”:{
"目标":一,,
“分数”:{
“$add”:计分条件
}
}},
//按最大“分数”排序(降序)
{“$sort”:{“score”:-1},
//返回第一个文档
{“$limit”:1}
],
函数(错误、结果){
//检查错误
//记住,结果是一个数组,即使仅限于一个文档
console.log(结果[0]);
}
)
因此,在处理聚合语句之前,我们将根据
userTarget
对象中的输入生成管道操作的动态部分。这将产生一个
或条件
,如下所示:

{“$match”:{
“$or”:[
{“target.cluster”:“01”},
{“target.env”:“DC”},
{“target.core”:“PO”}
]
}}
scoreCondition
将扩展为如下编码:

“分数”:{
“$add”:[
{“$cond”:[{“$eq”:[“$target.cluster”,“01”]},1,0]},
{“$cond”:[{“$eq”:[“$target.env”,“DC”]},1,0]},
{“$cond”:[{“$eq”:[“$target.core”,“PO”]},1,0]},
]
}
这些将用于选择可能的文档,然后计算可能匹配的术语。具体而言,“分数”是通过评估三元运算符内的每个条件得出的,然后在有匹配项的情况下归因于
1
,或者在该字段上没有匹配项的情况下归因于
0

如果需要,可以很简单地改变逻辑,为每个字段分配更高的“权重”,并根据比赛的重要性向分数方向分配不同的值。无论如何,您只需将每个字段的这些分数结果合并在一起即可获得总体“分数”

然后,只需对返回的“score”应用,然后使用返回顶部文档即可

这不是超高效的,因为即使这三个条件都匹配,但您对数据提出的基本问题不能假定存在,因此它需要查看“至少一个”条件匹配的所有数据,然后根据这些可能的结果计算出“最佳匹配”

理想情况下,我个人会“首先”运行一个额外的查询,以查看是否所有三个条件都满足,如果不满足,则查找其他情况。这仍然是两个独立的查询,不同于仅仅将所有字段的“and”条件作为
$或
中的第一条语句

因此,我认为首选的实施方式应该是:

  • 查找与所有给定字段值匹配的文档;如果没有,那么

  • 在每个字段上运行或,并计算条件匹配数


  • 这样,如果所有字段都匹配,则第一个查询速度最快,如果没有实际结果,只需返回清单中显示的较慢但必需的实现。

    您似乎要求返回满足最多条件的文档,可能不是所有条件。基本过程是一个
    $或
    查询,以返回可以匹配任一条件的文档。然后,您基本上需要一个语句来计算文档中满足了“多少条件”,并返回匹配最多的条件

    因此,这里的组合是一个语句,它使用的初始结果用于计算结果,然后对结果进行排序:

    //初始目标对象
    var userTarget={
    “集群”:“01”,
    “环境”:“DC”,
    “核心”:“PO”
    };
    //转换成美元或条件
    //与计算条件相匹配
    变量或条件=[],
    scoreCondition=[]
    key(userTarget).forEach(function(key){
    var query={},
    cond={“$cond”:[{“$eq”:[“$target.”+key,userTarget[key]]},1,0]};
    查询[“target.+key]=userTarget[key];
    orCondition.push(查询);
    计分条件推(秒);
    });
    //运行聚合
    模型集料(
    [
    //符合条件
    {“$match”:{“$or”:或条件},
    //根据匹配字段计算“分数”
    {“$project”:{
    "目标":一,,
    “分数”:{
    “$add”:计分条件
    }
    }},
    //按最大“分数”排序(降序)
    {“$sort”:{“score”:-1},
    //返回第一个文档
    {“$limit”:1}
    ],
    函数(err,res
    
    documents=[{
        targets:{
            "cluster":"01",
        }
    },{
        targets:{
            "cluster":"01",
            "env":"DC",
            "core":"PO"
        }
    },{
        targets:{
            "cluster":"01",
            "env":"DC",
            "core":"PO",
            "platform":"IG"
        }
    }];
    
    userTarget={
        "cluster":"01",
        "env":"DC",
        "core":"PO"
    }