在MongoDB中仅对不间断的序列进行分组

时间:2015-03-23 16:29:51

标签: mongodb

我有一系列按年份列出的项目。例如

{ id: 1, Make: "Audi", name: "A3", year: 1998 }
{ id: 2, Make: "Audi", name: "A3", year: 1999 }
{ id: 3, Make: "Audi", name: "A3", year: 2001 }
{ id: 4, Make: "Audi", name: "A3", year: 2002 }

我想按照品牌,名称,引擎尺寸等对数据进行分组......我希望将这些年份和内容推进到#34;年"元件。我的工作正常,但在上述数据中,您会注意到那一年:2000年缺失。

如何在MongoDB中汇总这些文档,以便最终获得两个结果:一个用于[1998,1999],另一个用于[2001,2002]?我可以轻松地设置一个检查值来检测序列中的间隙并在我的应用程序中处理它,但似乎从DB中获取它可能更清晰。

感谢。

1 个答案:

答案 0 :(得分:0)

我用MapReduce做了。

我想出了如果我可以选择"一个新的序列号(每个文档对0,1,2,3等),并从年份中减去它,它会给我一个检查值。例如:

seq: 1, year: 1998, check(year-seq): 1997
seq: 2, year: 1999, check(year-seq): 1997
seq: 3, year: 2001, check(year-seq): 1998
seq: 4, year: 2002, check(year-seq): 1998

现在我可以按检查值进行分组。但是如何生成此检查值?由于MongoDB聚合似乎不了解其他文档,并且不允许使用javascript,因此无法在每个查询的基础上创建递增序列。因此,我研究了MapReduce如何工作并产生以下内容:

db.cars.insert({Make: "Audi", name: "A3", year: 1998 })
db.cars.insert({Make: "Audi", name: "A3", year: 1999 })
db.cars.insert({Make: "Audi", name: "A3", year: 2001 })
db.cars.insert({Make: "Audi", name: "A3", year: 2002 })

db.cars.mapReduce(
    // map function
    function() {

        check = this.year - sequence;

        key = {
            make: this.Make,
            name: this.name,
            check: check,
        }

        value = { _id: this._id, year: this.year };
        emit(key, value);

        sequence++;

    }
    // end of map
    ,
    // reduce
    function(key, values) {
        var result = {individual_models: [] };
        values.forEach(function(v) {
            result.individual_models.push({ _id: v._id, year: v.year});
        });
        return result;
    }
    // end reduce
    ,
    {
        out: { inline: 1 },
        scope: { "sequence": 0},
    }
)

这给出了我的结果:

{
        "results" : [
                {
                        "_id" : {
                                "make" : "Audi",
                                "name" : "A3",
                                "check" : 1998
                        },
                        "value" : {
                                "individual_models" : [
                                        {
                                                "_id" : ObjectId("55115957f8198b539c3c41e4"),
                                                "year" : 1998
                                        },
                                        {
                                                "_id" : ObjectId("5511595df8198b539c3c41e5"),
                                                "year" : 1999
                                        }
                                ]
                        }
                },
                {
                        "_id" : {
                                "make" : "Audi",
                                "name" : "A3",
                                "check" : 1999
                        },
                        "value" : {
                                "individual_models" : [
                                        {
                                                "_id" : ObjectId("55115961f8198b539c3c41e6"),
                                                "year" : 2001
                                        },
                                        {
                                                "_id" : ObjectId("55115962f8198b539c3c41e7"),
                                                "year" : 2002
                                        }
                                ]
                        }
                }
        ],
        "timeMillis" : 1,
        "counts" : {
                "input" : 4,
                "emit" : 4,
                "reduce" : 2,
                "output" : 2
        },
        "ok" : 1,
}

可能需要更多测试以确保它能够为我的整个记录​​集工作,但它似乎就是我想要的。