我正在尝试在Riak 1.4上运行mapReduce查询,通过二级索引进行查询,按日期对记录进行排序,然后将结果限制为第一条记录。
我的二级索引查询工作正常。排序似乎没有做任何事情。排序没有错误,只返回未排序的结果。返回的记录数限制会产生服务器返回的“bad_json”错误。
这就是我所拥有的。假设查询“汽车”桶为“john_doe”拥有的最新汽车。 (有些名字已经改变以保护无辜者;):
JSSourceFunction dateSortFunction = new JSSourceFunction(
"function(v) {" +
"return v.sort(function(a, b) {" +
"return a.issueDate - b.issueDate ;" +
"}" +
");" +
"}");
IndexQuery iq = new BinValueQuery(BinIndex.named("person"), "cars", "john_doe");
MapReduceResult response = session.mapReduce(iq)
.addMapPhase(NamedErlangFunction.MAP_OBJECT_VALUE)
.addReducePhase(dateSortFunction)
.addReducePhase(new NamedJSFunction("Riak.reduceLimit"), 1)
.execute();
我看过很多关于排序的帖子,我希望最终能搞清楚。但是,我还没有看到任何有关LIMIT功能如何工作的帮助。
提前致谢!
更新 感谢Joe,他让我走上正轨。这是最终为我工作的东西。我的日期格式是ISO 8601(例如,2011-05-18T17:00:00-07:00)。所以,我可以通过词法比较正确的排序。另外,我找到了javascript的数组缩短方法并更新了代码以返回前5个对象。
JSSourceFunction sortLimitFunction = new JSSourceFunction(
"function(v) {" +
"v.sort(function(a, b) {" +
"return a.issueDate < b.issueDate" +
"}" +
");" +
"if (v.length > " + "5" + ") { " +
"v.length = " + "5" + ";" +
"}" +
"return v;" +
"}");
IndexQuery iq = new BinValueQuery(BinIndex.named("person"), "cars", "john_doe");
MapReduceResult response = session.mapReduce(iq)
.addMapPhase(new NamedJSFunction("Riak.mapValuesJson"))
.addReducePhase(sortLimitFunction)
.execute();
答案 0 :(得分:1)
对于排序,有一个涵盖此主题的mailing list post。我在该实现与您的实现之间看到的主要区别是在映射阶段使用JavaScript Riak.mapValuesJson函数。
对于限制,如果您只想要排序列表中的第一项,请尝试让sort函数仅返回第一个元素。虽然部分结果集从各种vnode到达时,reduce函数可以(并且可能)被多次调用,但是统一列表中的第一个元素也必须是它所源自的部分列表中的第一个元素,所以这应该给你什么您正在寻找:
JSSourceFunction dateSortFunction = new JSSourceFunction(
"function(v) {" +
"var arr = v.sort(function(a, b) {" +
"return a.issueDate - b.issueDate ;" +
"}" +
");" +
"if (arr.length == 0) { " +
"return [];" +
"} else {"
"return arr[0];" +
"}"
"}"
);