Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php mongodb中匹配的或条件的百分比_Php_Mongodb_Mongodb Query_Aggregation Framework_Mongodb Php - Fatal编程技术网

Php mongodb中匹配的或条件的百分比

Php mongodb中匹配的或条件的百分比,php,mongodb,mongodb-query,aggregation-framework,mongodb-php,Php,Mongodb,Mongodb Query,Aggregation Framework,Mongodb Php,我得到了以下格式的数据 { "_id" : ObjectId("534fd4662d22a05415000000"), "product_id" : "50862224", "ean" : "8808992479390", "brand" : "LG", "model" : "37LH3000", "features" : [{ { "key" : "Screen Format", "value" : "16:9", }, {

我得到了以下格式的数据

{
  "_id" : ObjectId("534fd4662d22a05415000000"),
  "product_id" : "50862224",
  "ean" : "8808992479390",
  "brand" : "LG",
  "model" : "37LH3000",
  "features" : [{
      {
      "key" : "Screen Format",
      "value" : "16:9",
    }, {
      "key" : "DVD Player / Recorder",
      "value" : "No",
    }, 
      "key" : "Weight in kg",
      "value" : "12.6",
    }
    ... so on
    ]
}
我需要将一个产品的功能与其他产品的功能进行比较,并根据功能匹配的百分比将结果分为单独的类别(100%匹配,50-99%匹配)

我最初的想法是为每个特性准备一个带有or条件的动态查询,并用php进行百分比计算,但这意味着mongodb将返回我,即使是那些只有1个特性匹配的产品。我认为几乎所有类别的产品都可能有一些共同的特性,所以我担心我可能正在用php开发很多产品

我基本上有两个问题

  • 有别的办法吗 我正在使用的数据结构足够好地支持我正在寻找的功能,或者我应该考虑改变它< /LI>
    我假设您希望将该系列的其余部分与给定产品进行比较,这是一个典型的聚合示例:

    lookingat = db.products.findOne({product_id:'50862224'})
    matches = db.products.aggregate([
        { $unwind: '$features' },
        { $match: { features: { $in: lookingat.features }}},
        { $group: { _id: '$product_id', matchedfeatures: { $sum:1 }}},
        { $sort: { matchedfeatures: -1 }},
        { $limit: 5 },
        { $project: { _id:0, product_id: '$_id',
                      pctmatch: { $multiply: [ '$matchedfeatures',
                                               100/lookingat.features.length ]}
          }}
    ])
    
    从集合中具有6个功能的产品的角度简要介绍这一点,并将其与具有4个功能的目标产品(“lookingat”)进行比较,其中3个功能匹配:

  • $unwind将具有6个功能的1个文档转换为6个相同的文档,每个文档具有1个功能
  • $match在目标的功能数组中查找该功能(请注意,只有当两个文档具有相同的字段名和值,且顺序相同时,这两个文档才是“相等的”),丢弃不匹配的3个文档,并传递匹配的3个文档
  • $group将使用这3个匹配的文档,并生成一个新文档,告诉您有3个文档与该产品标识匹配
  • $sort和$limit为您提供最相关的结果,并保留所有您所关心的单功能匹配
  • $project允许您将_id从$group步骤重新命名为product_id,并将匹配特征的数量计算为百分比(我们通过识别计算中的3个项中的2个是常量,可以在JS中进行分割,从而避免了$divide操作)

  • 我假设您希望将该系列的其余部分与给定产品进行比较,这是一个典型的聚合示例:

    lookingat = db.products.findOne({product_id:'50862224'})
    matches = db.products.aggregate([
        { $unwind: '$features' },
        { $match: { features: { $in: lookingat.features }}},
        { $group: { _id: '$product_id', matchedfeatures: { $sum:1 }}},
        { $sort: { matchedfeatures: -1 }},
        { $limit: 5 },
        { $project: { _id:0, product_id: '$_id',
                      pctmatch: { $multiply: [ '$matchedfeatures',
                                               100/lookingat.features.length ]}
          }}
    ])
    
    从集合中具有6个功能的产品的角度简要介绍这一点,并将其与具有4个功能的目标产品(“lookingat”)进行比较,其中3个功能匹配:

  • $unwind将具有6个功能的1个文档转换为6个相同的文档,每个文档具有1个功能
  • $match在目标的功能数组中查找该功能(请注意,只有当两个文档具有相同的字段名和值,且顺序相同时,这两个文档才是“相等的”),丢弃不匹配的3个文档,并传递匹配的3个文档
  • $group将使用这3个匹配的文档,并生成一个新文档,告诉您有3个文档与该产品标识匹配
  • $sort和$limit为您提供最相关的结果,并保留所有您所关心的单功能匹配
  • $project允许您将_id从$group步骤重新命名为product_id,并将匹配特征的数量计算为百分比(我们通过识别计算中的3个项中的2个是常量,可以在JS中进行分割,从而避免了$divide操作)

  • 您的解决方案应该是特定于MongoDB的,否则您将在客户端进行计算和可能的匹配,这对性能没有好处

    当然,您真正想要的是一种在服务器端进行处理的方法:

    db.products.aggregate([
    //匹配符合条件的文档
    {“$match”:{
    “$or”:[
    { 
    “特征”:{
    “$elemMatch”:{
    “键”:“屏幕格式”,
    “值”:“16:9”
    }
    }
    },
    { 
    “特征”:{
    “$elemMatch”:{
    “键”:“重量(kg)”,
    “值”:{“$gt”:“5”,“$lt”:“8”}
    }
    }
    },
    ]
    }},
    //保留文档和功能阵列的副本
    {“$project”:{
    “_id”:{
    “\u id”:“$\u id”,
    “产品id”:“$product\U id”,
    “ean”:“$ean”,
    “品牌”:“$brand”,
    “模型”:“$model”,
    “功能”:“$features”
    },
    “特色”:1
    }},
    //展开阵列
    {“$unwind”:“$features”},
    //查找与条件匹配的实际元素
    {“$match”:{
    “$or”:[
    { 
    “features.key”:“屏幕格式”,
    “特征值”:“16:9”
    },
    { 
    “features.key”:“重量单位为kg”,
    “features.value”:{“$gt”:“5”,“$lt”:“8”}
    },
    ]
    }},
    //数一数那些匹配的元素
    {“$组”:{
    “\u id”:“$\u id”,
    “计数”:{“$sum”:1}
    }},
    //恢复文档并将匹配的元素除以
    //处于“或”状态的元素数
    {“$project”:{
    “\u id”:“$\u id.\u id”,
    “产品id”:“$\u id.产品id”,
    “ean”:“$\u id.ean”,
    “品牌”:“$\u id.brand”,
    “模型”:“$\u id.model”,
    “功能”:“$\u id.features”,
    “匹配”:{“$divide”:[“$count”,2]}
    }},
    //按匹配的百分比排序
    {“$sort”:{“matched”:-1}
    ])
    
    因此,当您知道要应用的
    $或
    条件的“长度”时,您只需找出“features”数组中有多少元素与这些条件匹配。这就是管道中第二个$match的全部内容

    一旦你有了这个计数,你只需除以作为你的
    $或
    传入的条件数。我喜欢这里的美丽