当前位置:  开发笔记 > 前端 > 正文

在CouchDB中进行一对多"JOIN"的最佳方法

如何解决《在CouchDB中进行一对多"JOIN"的最佳方法》经验,为你挑选了1个好方法。

我正在寻找一个等同于"SQL连接"的CouchDB.

在我的示例中,有些CouchDB文档是列表元素:

{ "type" : "el", "id" : "1", "content" : "first" } 
{ "type" : "el", "id" : "2", "content" : "second" } 
{ "type" : "el", "id" : "3", "content" : "third" } 

有一个文档定义了列表:

{ "type" : "list", "elements" : ["2","1"] , "id" : "abc123" }

如您所见,第三个元素已被删除,它不再是列表的一部分.所以它不能成为结果的一部分.现在我想要一个返回内容元素的视图,包括正确的顺序.

结果可能是:

{ "content" : ["second", "first"] }

在这种情况下,元素的顺序已经是应该的.另一个可能的结果

{ "content" : [{"content" : "first", "order" : 2},{"content" : "second", "order" : 1}] }

我开始编写地图功能:

map = function (doc) {
  if (doc.type === 'el') {
    emit(doc.id, {"content" : doc.content}); //emit the id and the content
    exit;
  }
  if (doc.type === 'list') {
    for ( var i=0, l=doc.elements.length; i

这是我能得到的.你能纠正我的错误并写一个reduce函数吗?请记住,第三个文档不得是结果的一部分.

当然你也可以写一个不同的地图功能.但是文档的结构(一个definig元素文档和每个条目的条目文档)不能改变.


编辑:不要错过JasonSmith对他的答案的评论,他在那里描述了如何做到这一点.



1> JasonSmith..:

谢谢!这是展示CouchDB 0.11新功能的一个很好的例子!

您必须使用与提取相关的数据功能来引用视图中的文档.或者,为了更方便的JSON,使用_list函数来清理结果.有关详细信息,请参阅Couchio关于"JOIN"的文章.

这是计划:

    首先,您的el文档具有唯一性约束.如果其中两个id = 2,那就是问题所在.如果是,则必须使用该_id字段id.CouchDB将保证唯一性,但此计划的其余部分也需要_id按ID获取文档.

    { "type" : "el", "_id" : "1", "content" : "first" } 
    { "type" : "el", "_id" : "2", "content" : "second" } 
    { "type" : "el", "_id" : "3", "content" : "third" } 
    

    如果_id无法更改要使用的文档,则可以创建一个简单的视图emit(doc.id, doc),然后将其重新插入临时数据库.这转化id_id但增加了一些复杂性.

    视图会发出{"_id": content_id}键入的数据 [list_id, sort_number],以便用其内容"聚集"列表.

    function(doc) {
      if(doc.type == 'list') {
        for (var i in doc.elements) {
          // Link to the el document's id.
          var id = doc.elements[i];
          emit([doc.id, i], {'_id': id});
        }
      }
    }
    

    现在有一个简单的el文档列表,按正确的顺序排列.您可以使用startkey,endkey如果您只想查看特定列表.

    curl localhost:5984/x/_design/myapp/_view/els
    {"total_rows":2,"offset":0,"rows":[
    {"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","0"],"value":{"_id":"2"}},
    {"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","1"],"value":{"_id":"1"}}
    ]}
    

    要获取el内容,请使用include_docs=true.通过魔术 _id,el文件将加载.

    curl localhost:5984/x/_design/myapp/_view/els?include_docs=true
    {"total_rows":2,"offset":0,"rows":[
    {"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","0"],"value":{"_id":"2"},"doc":{"_id":"2","_rev":"1-4530dc6946d78f1e97f56568de5a85d9","type":"el","content":"second"}},
    {"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","1"],"value":{"_id":"1"},"doc":{"_id":"1","_rev":"1-852badd683f22ad4705ed9fcdea5b814","type":"el","content":"first"}}
    ]}
    

    请注意,这已经是您需要的所有信息.如果您的客户端非常灵活,您可以使用此JSON解析信息.下一个可选 步骤只需重新格式化以匹配您所需的内容.

    使用一个_list函数,它只是重新格式化视图输出.人们使用它们来输出XML或HTML,但是我们会使JSON更方便.

    function(head, req) {
      var headers = {'Content-Type': 'application/json'};
      var result;
      if(req.query.include_docs != 'true') {
        start({'code': 400, headers: headers});
        result = {'error': 'I require include_docs=true'};
      } else {
        start({'headers': headers});
        result = {'content': []};
        while(row = getRow()) {
          result.content.push(row.doc.content);
        }
      }
      send(JSON.stringify(result));
    }
    

    结果匹配.当然,在生产中,您将需要startkeyendkey指定所需的列表.

    curl -g 'localhost:5984/x/_design/myapp/_list/pretty/els?include_docs=true&startkey=["abc123",""]&endkey=["abc123",{}]'
    {"content":["second","first"]}
    


一句话,这是彻底的.好工作jhs!
这是误导性的.实际上,第2步是一个完整的解决方案,但是,我是详细的背景要求和在客户端增加便利性的可选方法.
推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有