0

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

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 函数,以便它在键中显示用户和日期(作为要排序的字段)

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”,但没有任何改变。所以...有什么想法吗?据我在其他类似问题中看到的,人们只是使用 {} 作为结束键并离开 startkey 而没有第二个参数,但这在这里也不起作用。

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

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});
  }
};

如果在设置开始键和结束键之前将descending 设置为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...
    }
});

这成功了,它完美地工作(但也完全没有逻辑)。

4

3 回答 3

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时,你首先颠倒顺序。以前,您在descending=false时以应有的方式设置开始键和结束键,但在更改降序时需要反转它们。CouchDB 权威指南很棒,它讨论了这些相反的结果,值得一读。

我完全错过了你正在下降,很抱歉造成混乱。

于 2013-05-14T15:07:57.490 回答
0

我认为 startkey [save_profile, null] 是什么让你搞砸了(尽管它通过 curl 工作)。无论您使用什么库(db.view 可能是一些 javascript lib 或 ruby​​ CouchRest?)都可能将 null 重新编码为其他内容。与 curl 相比,您始终可以通过断开数据包嗅探器(即 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,我只是将键的那个元素留在了外面。还要注意 curl (可能你是图书馆),你必须非常小心你在开始/结束键中输入的内容。我必须转义所有即使单引号也无法转义的 bash 内容(即 [ { 等),并且 curl 将空格转义为 %20,然后将其用于键。一个好的方法是不分叉运行 couchdb,或者只是查看它的日志,看看传入的请求是什么样的。对我来说一直是问题的根源。

您在键中使用通配符,这是一个很酷的功能。您可能已经看过这个,我已经重读了几次这个片段以试图理解它们。

在我真正理解视图的作用之前,我也曾在类似的问题上打过头。但是你正在做的应该是可能的。任何更复杂的搜索,我真的会考虑 Elasticsearch 或类似的东西。河流安装非常简单,查询非常相似。但是您不必绕过视图和顺序的限制。

希望有帮助。

于 2013-05-13T15:23:59.663 回答
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});
  }
};

如果在设置开始键和结束键之前将descending 设置为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...
    }
});

这成功了,它完美地工作(但也完全没有逻辑)。

于 2013-05-14T13:04:19.957 回答