且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

CouchDB-从列表中过滤每个记录的实例的最新日志

更新时间:2023-12-01 15:30:28

这就是我要做的.这是严重的CouchDB滥用,但是我取得了很大的成功.

Here is what I do. This is borderline CouchDB abuse however I have had much success.

通常,reduce将计算总和,计数或类似的东西.但是,将reduce视为淘汰赛.引入了许多价值.只有一个价值出现.减少!重复一遍又一遍,您将获得最终的胜利者(再减少).在这种情况下,具有最新时间戳的日志将成为赢家.

Usually, reduce will compute a sum, or a count, or something like that. However, think of reduce as an elimination tournament. Many values go in. Only one comes out. A reduction! Repeat over and over and you have the ultimate winner (a re-reduction). In this case, the log with the latest timestamp is the winner.

当然,次中量级不能与重量级对抗.必须有联赛和举重课.对于某些文档与某些其他类似文档进行斗争,才有意义.这正是reduce group 参数所要执行的操作.这将确保只有均匀匹配的角斗士才能进入我们的血统运动中的钢制笼子. (咖啡在踢.)

Of course, welterweights can't fight heavyweights. There have to be leagues and weight classes. It only makes sense for certain documents to do battle with certain other similar documents. That is exactly what the reduce group parameter will do. It will ensure that only evenly-matched gladiators enter the steel cage in our bloodsport. (Coffee is kicking in.)

首先,发出所有由设备键入的日志.发出的value只是文档的副本.

First, emit all logs keyed by device. The value emitted is simply a copy of the document.

function(doc) {
    emit(doc.name, doc);
}

接下来,编写一个reduce函数以返回所有给定值的最新时间戳.如果您看到来自不同联盟的两个角斗士之间的战斗(来自不同系统的两个原木),请停止战斗!出了点问题(有人查询了错误的group值).

Next, write a reduce function to return the latest timestamp of all given values. If you see a fight between two gladiators from different leagues (two logs from different systems), stop the fight! Something went wrong (somebody queried without the correct group value).

function(keys, vals, re) {
    var challenger, winner = null;
    for(var a = 0; a < vals.length; a++) {
        challenger = vals[a];
        if(!winner) {
            // The title is unchallenged. This value is the winner.
            winner = challenger;
        } else {
            // Fight!
            if(winner.name !== challenger.name) {
                // Stop the fight! He's gonna kill him!
                return null; // With a grouping query, this will never happen.
            } else if(winner.timestamp > challenger.timestamp) {
                // The champ wins! (Nothing to do.)
            } else {
                // The challenger wins!
                winner = challenger;
            }
        }
    }

    // Today's champion lives to fight another day.
    return winner;
}

(注意,时间戳比较可能是错误的.您可能必须转换为Date.)

(Note, the timestamp comparison is probably wrong. You will have to convert to a Date probably.)

现在,当您使用?group=true查询视图时,CouchDB将仅减少具有相同key(即您的计算机名称)的值(在其中找到胜者).

Now, when you query a view with ?group=true, then CouchDB will only reduce (find the winner between) values with the same key, which is your machine name.

(您还可以发出一个数组作为键,这提供了更多的灵活性.您可以使用emit([doc.name, doc.timestamp], doc)代替.因此,您可以使用?reduce=false&startkey=["NAS", null]&endkey=["NAS", {}]之类的查询按系统查看所有日志,也可以按以下方式查看最新日志: ?group_level=1的系统.

(You can also emit an array as a key, which gives a bit more flexibility. You could emit([doc.name, doc.timestamp], doc) instead. So you can see all logs by system with a query like ?reduce=false&startkey=["NAS", null]&endkey=["NAS", {}] or you could see latest logs by system with ?group_level=1.

最后,停止战斗"是可选的.您可以简单地始终返回带有最新时间戳的文档.但是,我更喜欢保留它,因为在类似的情况下,我想看看我是否正确进行了地图缩小,而我的主要提示是null缩小输出.

Finally, the "stop the fight" stuff is optional. You could simply always return the document with the latest timestamp. However, I prefer to keep it there because in similar situations, I want to see if I am map-reducing incorrectly, and a null reduce output is my big clue.