当降序为真时,Couchdb会反转开始和结束键

时间:2013-05-13 13:24:49

标签: javascript couchdb

我有一个CouchDB,其中包含名为save_data(我需要的实际数据),rel(作为相关帐户 - 链接到该文档的帐户)和created_at(创建日期)的项目。 当我第一次创建我称为最近项目的视图时,我认为该视图中的项目按照它们的创建顺序进行排序,但是我没多久就发现了我的错误。我想获取与一个用户相关的所有文档(我的js中的rel,save_profile调用db.view函数),然后根据created_at对它们进行排序,这样我创建了map funcion:

function(doc) {
  if (doc.rel) {
  var p = doc.save_data || {};
  var r = doc.rel || {};
  var q = doc.created_at || {};
  emit([doc.rel], {save_data: doc.save_data, rel: doc.rel});
  }
};

然后我用这些参数调用它:

db.view(design + "/recent-items", {
    descending : "true",
    limit : 10,
    update_seq : true,
    key : [save_profile],
    success : function(data) {
        ...somecode...
}
});

然后我注意到它们并没有按照我想要的顺序出现,而是按照现在有意义的ID排序,但这不是我需要的。所以我这样做了:我重新设计了map函数,以便在key中显示用户和日期(作为要排序的字段)

function(doc) {
  if (doc.rel) {
  var p = doc.save_data || {};
  var r = doc.rel || {};
  var q = doc.created_at || {};
  emit([doc.rel, doc.created_at], {save_data: doc.save_data, rel: doc.rel});
  }
};

然后我在db.view中使用了startkey而不是key:

db.view(design + "/recent-items", {
    descending : "true",
    limit : 10,
    update_seq : true,
    startkey : [save_profile, null],
    success : function(data) {
        ...somecode...
}
});

这样我就可以获得与save_profile相关的所有文档,但也按日期排序。我确实得到了它们,但我也从其他用户那里获得了文档,因此功能完全不可靠。我所做的就是实现endkey,就像这样:

db.view(design + "/recent-items", {
    descending : "true",
    limit : 10,
    update_seq : true,
    startkey : [save_profile, null],
    endkey : [save_profile, {}],
    success : function(data) {
        ...somecode...
}
});

然后我得到空视图结果。 我使用的日期是这种格式:

"2013-05-13T11:59:22.281Z"

和个人资料是这样的:

{"rand":"0.26928815129213035","nickname":"Nickname","email":"Label for Gravatar","url":"URL","gravatar_url":"http://www.gravatar.com/avatar/35838c85593335493a1fa916863fee0c.jpg?s=40&d=identicon","name":"testacc"}

我也尝试用“0000-00-00T00:00:00.000Z”和“9999-99-99T99:99:99.999Z”替换start / endkeys中的[]和{},但它没有改变任何内容。所以...任何想法?就我在其他类似问题中看到的那样,人们只使用{}作为结束键而没有第二个参数就离开了启动键,但这在这里也不起作用。

编辑:解决了! 好的伙计,不管你信不信,我是这样做的: 我将地图功能更改为以这种方式创建的显示和配置文件:

function(doc) {
  if (doc.rel) {
  var p = doc.save_data || {};
  var r = doc.rel || {};
  var q = doc.created_at || {};
  emit([doc.rel, doc.created_at], {save_data: doc.save_data, rel: doc.rel});
  }
};

并且看起来如果在设置开始和结束键之前将降序设置为true,则必须反转搜索间隔,以便endkey包含起始值,startkey包含结束值,如下所示:

db.view(design + "/recent-items", {
    descending : "true",
    update_seq : "true",
    startkey : [save_profile.name, save_profile.rand, {}],
    endkey : [save_profile.name, save_profile.rand, null],
    inclusive_end : "true",
    success : function(data) {
        ...somecode...
    }
});

这就是诀窍,它完美无缺(但完全没有逻辑)。

3 个答案:

答案 0 :(得分:4)

我之前应该抓住这个。因此,当您执行以下操作时,它会以您希望的方式运行:

db.view('_design/test_views/_view/view1', startkey: ["account2"])
 => {"total_rows"db.view('_design/test_views/_view/view1')
 => {"total_rows"=>4, "offset"=>0, "rows"=>[{"id"=>"test1", "key"=>["account1", "2009-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account1"}}, {"id"=>"test2", "key"=>["account2", "2012-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account2"}}, {"id"=>"test3", "key"=>["account3", "2011-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account3"}}, {"id"=>"test4", "key"=>["account4", "2010-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account4"}}]}`
db.view('_design/test_views/_view/view1',startkey: ["account2"])
 => {"total_rows"=>4, "offset"=>1, "rows"=>[{"id"=>"test2", "key"=>["account2", "2012-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account2"}}, {"id"=>"test3", "key"=>["account3", "2011-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account3"}}, {"id"=>"test4", "key"=>["account4", "2010-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account4"}}]}`
db.view('_design/test_views/_view/view1',
     startkey: ["account2"],
     endkey: ["account3",{}])
 => {"total_rows"=>4, "offset"=>1, "rows"=>[{"id"=>"test2", "key"=>["account2", "2012-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account2"}}, {"id"=>"test3", "key"=>["account3", "2011-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account3"}}]}`. 

当您设置 descending = true 时,请先颠倒订单。以前,您按照降序=假时的方式设置开始和结束键,但是在更改降序时需要将其反转。 CouchDB权威指南很棒,并且讨论了这些reversed results,值得一读。

我完全错过了你正在设置下降,抱歉混淆。

答案 1 :(得分:0)

我认为startkey [save_profile,null]正在弄乱你(虽然它可以通过curl工作)。你使用的是什么库(db.view是一些javascript lib或ruby CouchRest可能?)可能会将null重新编码为其他内容。你可以通过打破数据包嗅探器(即Wireshark)来验证这与curl相比,尽管你会知道库对于它所做的所有额外请求是多么低效。可以使故障排除更加困难。

卷曲会得到什么结果?我嘲笑了你的数据库,这就是我得到的:

$ curl -X GET 'http://localhost:5984/test2/_design/test_views/_view/view1'
{"total_rows":4,"offset":0,"rows":[
{"id":"test1","key":["account1","2009-05-13T11:59:22.281Z"],"value":{"rel":"account1"}},
{"id":"test2","key":["account2","2012-05-13T11:59:22.281Z"],"value":{"rel":"account2"}},
{"id":"test3","key":["account3","2011-05-13T11:59:22.281Z"],"value":{"rel":"account3"}},
{"id":"test4","key":["account4","2010-05-13T11:59:22.281Z"],"value":{"rel":"account4"}}
]}

$ curl -X GET 'http://localhost:5984/test2/_design/test_views/_view/view1?startkey=\["account2"\]&endkey=\["account3",\{\}\]'
{"total_rows":4,"offset":1,"rows":[
{"id":"test2","key":["account2","2012-05-13T11:59:22.281Z"],"value":{"rel":"account2"}},
{"id":"test3","key":["account3","2011-05-13T11:59:22.281Z"],"value":{"rel":"account3"}}
]}

请注意,我没有使用null,我只是将键的元素保留。另外请注意卷曲(可能是你的库),你必须非常小心你放入开始/结束键。我必须逃避所有bash的东西,即使单引号也不会逃脱(即[{etc),curl将空格转换为%20,然后将其用于键。一个好的方法是运行couchdb而不是分叉,或只是查看它的日志,看看传入的请求是什么样的。一直是我的问题来源。

您在按键中使用通配符,这是一个很酷的功能。您可能已经看过this,我已经多次重读这段代码以尝试理解它们。

我也在这个类似的问题上击败了我的头脑,直到我真正了解了哪些观点。但是你所做的应该是可能的。任何更复杂的搜索,我真的考虑Elasticsearch或类似的东西。河流安装非常简单,查询非常相似。但是您不必解决视图和订单的限制。

希望有所帮助。

答案 2 :(得分:0)

好的伙计,不管你信不信,我是这样做的: 我将地图功能更改为以这种方式创建的显示和配置文件:

function(doc) {
  if (doc.rel) {
  var p = doc.save_data || {};
  var r = doc.rel || {};
  var q = doc.created_at || {};
  emit([doc.rel, doc.created_at], {save_data: doc.save_data, rel: doc.rel});
  }
};

并且看起来如果在设置开始和结束键之前将降序设置为true,则必须反转搜索间隔,以便endkey包含起始值,startkey包含结束值,如下所示:

db.view(design + "/recent-items", {
    descending : "true",
    update_seq : "true",
    startkey : [save_profile.name, save_profile.rand, {}],
    endkey : [save_profile.name, save_profile.rand, null],
    inclusive_end : "true",
    success : function(data) {
        ...somecode...
    }
});

这就是诀窍,它完美无缺(但完全没有逻辑)。