我可以使用一些帮助从couchdb视图中过滤不同的值。 我有一个数据库,用于存储包含计算机信息的日志。 定期将计算机的新日志写入db。
有点简化我存储这样的条目:
{
"name": "NAS",
"os": "Linux",
"timestamp": "2011-03-03T16:26:39Z",
}
{
"name": "Server1",
"os": "Windows",
"timestamp": "2011-02-03T19:31:31Z",
}
{
"name": "NAS",
"os": "Linux",
"timestamp": "2011-02-03T18:21:29Z",
}
到目前为止,我正在努力通过不同的条目过滤此列表。 我想收到的是每个设备的最新日志文件。
我有这样的观点:
function(doc) {
emit([doc.timestamp,doc.name], doc);
}
我用python(couchdbkit)查询这个视图,到目前为止我提出的最佳解决方案看起来像这样:
def get_latest_logs(cls):
unique = []
for log in cls.view("logs/timestamp", descending=True):
if log.name not in unique_names:
unique.append(log)
return unique
好的......这很有效。但我有强烈的感觉,这不是最好的解决方案,因为python需要迭代整个日志文件列表(可能会变得很长)。
我想我需要一个reduce功能,但我找不到任何例子 或解释我可以适应我的问题。
所以,我正在寻找的是一个(纯粹的couchdb)视图,它只会吐出给定设备的最新日志。
答案 0 :(得分:6)
这是我的工作。这是边缘CouchDB滥用,但我已经取得了很大的成功。
通常,reduce
会计算总和,或计数等。但是,将reduce视为淘汰赛。许多价值观都在流传。只有一个值出现。减少!一遍又一遍地重复,你有最终的赢家(重新减少)。在这种情况下,具有最新时间戳的日志是赢家。
当然,welterweights无法对抗重量级人物。必须有联赛和重量级。只有某些文档与某些其他类似文档进行战斗才有意义。这正是reduce 组参数的作用。它将确保只有均匀匹配的角斗士进入我们的血液运动中的钢笼。 (咖啡正在踢。)
首先,发出设备键入的所有日志。发出的value
只是文档的副本。
function(doc) {
emit(doc.name, doc);
}
接下来,编写reduce函数以返回所有给定值的最新时间戳。如果你看到来自不同联赛的两个角斗士之间的斗争(来自不同系统的两个日志),请停止战斗!出了点问题(有人在没有正确的group
值的情况下查询。)
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
。)
现在,当您使用?group=true
查询视图时,CouchDB只会使用相同的key
(您的计算机名称)减少(找到之间的赢家)值。
(您也可以将数组作为键发出,这样可以提供更多的灵活性。您可以emit([doc.name, doc.timestamp], doc)
代替。所以您可以通过系统查看所有日志,例如?reduce=false&startkey=["NAS", null]&endkey=["NAS", {}]
或者您可以按系统查看?group_level=1
的最新日志。
最后,“停止战斗”的东西是可选的。您可以随时返回带有最新时间戳的文档。但是,我更喜欢将它保留在那里,因为在类似的情况下,我想看看我是否正确地减少了地图,并且null减少输出是我的大线索。