【问题标题】:Mongo custom multikey sortingMongodb自定义多键排序
【发布时间】:2012-04-07 01:14:09
【问题描述】:

Mongo docs 状态:

Mongo 多键功能可以自动索引值数组。

这很好。但是基于多键的排序呢?更具体地说,如何根据数组匹配百分比对集合进行排序

例如,我有一个模式[ 'fruit', 'citrus' ] 和一个集合,看起来像这样:

{
    title: 'Apples',
    tags: [ 'fruit' ]
},

{
    title: 'Oranges',
    tags: [ 'fruit', 'citrus' ]
},

{
    title: 'Potato',
    tags: [ 'vegetable' ]
}

现在,我想根据每个条目与标签模式的匹配百分比对集合进行排序。橙子必须先来,苹果次之,土豆最后。

什么是最有效和最简单的方法?

【问题讨论】:

  • 您能更清楚地了解排序的目标是什么吗?是按照匹配百分比排序吗?例如与数组的所有元素匹配的所有文档(在本例中为水果和柑橘),然后是仅匹配水果的文档,然后是仅匹配柑橘的文档,等等?
  • @Barrie,是的,完全正确。更新了问题。

标签: node.js mongodb sorting multikey nosql


【解决方案1】:

注意:Mongo 2.0 及更早版本需要以下说明。对于更高版本,您应该考虑新的聚合框架。

我们在尝试模糊匹配我们索引的输入句子时做了类似的事情。每次获得匹配项时,您都可以使用 map reduce 发出对象 ID,并将它们相加。然后,您需要将结果加载到您的客户端并首先按最高值排序。

db.plants.mapReduce(
    function () {
        var matches = 0;
        for (var i = 0; i < targetTerms.length; i++) {
            var term = targetTerms[i];
            for (var j = 0; j < this.tags.length; j++) {
                matches += Number(term === this.tags[j]);
            }   
        }   
        emit(this._id, matches);
    },  

    function (prev, curr) {
        var result = 0;
        for (var i = 0; i < curr.length; i++) {
            result += curr[i];
        }   
        return result;
    },  

    {   
        out: { inline: 1 },

        scope: {
            targetTerms: [ 'fruit', 'oranges' ],
        }   
    }   
);

您可以在 map reduce 调用中使用 scope 参数将 ['fruit', 'citrus' ] 输入值作为 {targetTerms: ['fruit', 'citrus' ]} 传递,以便它们在上面的 map 函数中可用。

【讨论】:

    【解决方案2】:

    从 MongoDB 2.1 开始,可以使用聚合框架完成类似的计算。语法类似于

    db.fruits.aggregate(
         {$match : {tags : {$in : ["fruit", "citrus"]}}}, 
         {$unwind : "$tags"}, 
         {$group : {_id : "$title", numTagMatches : {$sum : 1}}}, 
         {$sort : {numTagMatches : -1}} )
    

    返回

     {
       "_id" : "Oranges",
       "numTagMatches" : 2
     },
     {
       "_id" : "Apples",
       "numTagMatches" : 1
     }
    

    这应该比 map-reduce 方法快得多,原因有两个。首先是因为实现是本机 C++ 而不是 javascript。其次,因为 "$match" 将过滤掉根本不匹配的项目(如果这不是您想要的,您可以省略 "$match" 部分,并将 "$sum" 部分更改为1 或 0 取决于标签是否等于“水果”或“柑橘”或两者都不相同)。

    这里唯一需要注意的是,mongo 2.1 不推荐用于生产。如果您在生产中运行,则需要等待 2.2。但是,如果您只是自己进行试验,则可以使用 2.1,因为聚合框架应该更高效。

    【讨论】:

    • 谢谢,matulef!语法也很好。
    猜你喜欢
    • 2020-11-25
    • 1970-01-01
    • 2012-11-09
    • 1970-01-01
    • 2019-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多