2014-02-07 73 views
6

我想根据一个特定字段找到最大连续记录数。根据Mongodb中的一个字段查找最大连续记录数

db.people收集查找排序基于现场后:

> db.people.find().sort({ updated_at: 1}) 
{ "_id" : 1, "name" : "aaa", "flag" : true, "updated_at" : ISODate("2014-02-07T08:42:48.688Z") } 
{ "_id" : 2, "name" : "bbb", "flag" : false, "updated_at" : ISODate("2014-02-07T08:43:10Z") } 
{ "_id" : 3, "name" : "ccc", "flag" : true, "updated_at" : ISODate("2014-02-07T08:43:40.660Z") } 
{ "_id" : 4, "name" : "ddd", "flag" : true, "updated_at" : ISODate("2014-02-07T08:43:51.567Z") } 
{ "_id" : 6, "name" : "fff", "flag" : false, "updated_at" : ISODate("2014-02-07T08:44:23.713Z") } 
{ "_id" : 7, "name" : "ggg", "flag" : true, "updated_at" : ISODate("2014-02-07T08:44:44.639Z") } 
{ "_id" : 8, "name" : "hhh", "flag" : true, "updated_at" : ISODate("2014-02-07T08:44:51.415Z") } 
{ "_id" : 5, "name" : "eee", "flag" : true, "updated_at" : ISODate("2014-02-07T08:55:24.917Z") } 

在上面记录,存在flag属性值在连续的方式来true两个地方。即

record with _id 3 - record with _id 4 (2 consecutive records) 

record with _id 7 - record with _id 8 - record with _id 5 (3 consecutive records) 

不过,我想从蒙戈查询搜索的最大连续编号。即3

可以得到这样的结果吗?

我把它搜索了一下,发现有一点类似的解决方法,在这里使用Map-Reducehttps://stackoverflow.com/a/7408639/1120530

我是mongodb的新手,无法理解map-reduce文档,特别是如何将其应用于上述场景。

+0

你可以澄清,如果你的意思是“最连续的记录”,当按特定关键字段排序或者你在寻找插入的自然顺序时。如果人们在提问时了解你的用例,它会有所帮助。这避免了你以后说,这个回应完全不是你想要的。 –

+0

@NeilLunn:请检查我更新的问题。 – ram

+0

你可以用javascript表达来实现它(注意它会很慢)。据我所知,没有mongo原生查询。 –

回答

5

你可以做mapReduce操作。

首先映射器:

var mapper = function() { 


    if (this.flag == true) { 
     totalCount++; 
    } else { 
     totalCount = 0; 
    } 

    if (totalCount != 0) { 
     emit (
     counter, 
     { _id: this._id, totalCount: totalCount } 
    ); 
    } else { 
     counter++; 
    } 

}; 

这使该true值旗看到的总的时间的运行计数。如果该数超过1,则我们发出该值,也包含文档_id。当标志为false时,用于该键的另一个计数器递增,以便为匹配具有分组“键”。

然后,减速机:

var reducer = function (key, values) { 

    var result = { docs: [] }; 

    values.forEach(function(value) { 
     result.docs.push(value._id); 
     result.totalCount = value.totalCount; 
    }); 

    return result; 

}; 

只需推动_id值到具有沿TOTALCOUNT结果阵列。

然后运行:

db.people.mapReduce(
    mapper, 
    reducer, 
    { 
     "out": { "inline": 1 }, 
     "scope": { 
      "totalCount": 0, 
      "counter": 0 
     }, 
     "sort": { "updated_at": 1 } 
    } 
) 

所以与mapperreducer功能,我们再定义“范围”中使用全局变量,并通过在被要求对updated_at日期的“排序”。其给出结果:

{ 
    "results" : [ 
     { 
      "_id" : 1, 
      "value" : { 
       "docs" : [ 
        3, 
        4 
       ], 
       "totalCount" : 2 
      } 
     }, 
     { 
      "_id" : 2, 
      "value" : { 
      "docs" : [ 
       7, 
       8, 
       5 
      ], 
      "totalCount" : 3 
      } 
     } 
    ], 
    "timeMillis" : 2, 
    "counts" : { 
      "input" : 7, 
      "emit" : 5, 
      "reduce" : 2, 
      "output" : 2 
    }, 
    "ok" : 1, 
} 

当然,你可以只跳过totalCount变量,需要使用数组的长度,这将是相同的。但是既然你想使用这个计数器,它只是被添加进来。但这就是原理。

所以是的,这是一个适合mapReduce的问题,现在你有一个例子。

+0

感谢您的回复。 – ram

+0

@NeilLunn,尼斯答案,你在哪里? – Disposer

相关问题