基于对象属性值在Cloudant(CouchDB)中创建视图

时间:2013-05-01 06:37:35

标签: couchdb cloudant

我一直在努力寻找这个要求的解决方案,但我遇到了许多死胡同。

我正在使用 Cloudant 作为用户文档的数据存储。每个用户文档都有一个名为“items”的字段(属性),它是一个对象数组。

因此用户文档如下所示:

{
    "_id":"userid1",
    "_rev":"XX",
    "username": "foobaruser"
    "items":
    [
      {
          "date":1357879144069,
          "text":"don't cry because it's over, smile because it happened.",
          "cat":"determination"
      },
      {
          "date":1357879179209,
          "text":"those who mind don't matter, and those who matter don't mind.",
          "cat":"fitness"
      },
      {
          "date":1357883809736,
          "text":"be the change that you wish to see in the world.",
          "cat":"determination"
      },
      {
          "date":1357879179209,
          "text":"those who mind don't matter, and those who matter don't mind.",
          "cat":"hardwork"
      },
      {
          "date":1357879179209,
          "text":"those who mind don't matter, and those who matter don't mind.",
          "cat":"determination"
      }
   ]
}
  • 数据存储中有多个这样的用户文档,每个文档都有“items”属性

要求:

  1. 理想情况下,我想在视图上使用搜索功能并传入“cat”的值,然后返回所有与“cat”值匹配的文档中的所有“项目”。

    e.g。 HTTPS:// [用户名] .cloudant.com / DBNAME / _design /视图/ _search / DOC Q =判定

  2. 上述搜索将返回所有用户文档中“items”中的所有对象,其中“cat = determination”的格式与此类似:

    {
        "total_rows": 2,
        "rows": 
        [{
            "id": "userid1",
            "items": 
            [
                {
                    "date":1357879144069,
                    "text":"don't cry because it's over, smile because it happened.",
                    "cat":"determination"
                },
                {
                    "date":1357883809736,
                    "text":"be the change that you wish to see in the world.",
                    "cat":"determination"
                },
                {
                   "date":1357879179209,
                   "text":"those who mind don't matter, and those who matter don't mind.",
                   "cat":"determination"
                }
            ]
        },
        {
            "id": "userid2",
            "items": 
            [
                {
                    "date":135787966655,
                    "text":"Some text",
                    "cat":"determination"
                }
            ]
        }]
    }
    
  3. 如果使用“搜索”无法做到这一点,那么是否可以使用二级索引来实现这一目标?

3 个答案:

答案 0 :(得分:5)

在CouchDB中,您无法将查询参数的动态值传递给视图(在您的情况下为cat = determination)。 CouchDB中的方法是创建一个更通用的视图,然后在调用视图以获取所需数据时调整结果的排序方式。

您需要在db的设计文档中创建自定义视图才能实现此目的:

byUserItemCat: {
    map: function (doc) {
        if ( !doc.items || doc.items.length === 0 ) return;
        for ( var i=0; i<doc.items.length; i++ ) {
            emit(doc.items[i].cat,{doc._id,doc.items[i].date,doc.items[i].text});
        }
    }
}

因此,上面的视图将获取db中的每个doc,检查它是否包含带有内容的items数组,然后遍历所有doc的项目。对于每个item元素,它会将cat作为索引发送到结果集中,这很重要,因为我们可以针对此索引进行排序。我们可以自由地构建结果对象(emit的第二个参数),在上面的例子中,我构建了一个具有用户ID的对象,以及项目&#39;日期和文字。

您可以调用此类视图来获取所有结果:

curl -X GET http://127.0.0.1:5984/<db-name>/_design/<design-doc-name>/_view/byUserItemCat

如果您只对索引键(即cat)的结果感兴趣,那么&#34;确定&#34;你做了:

curl -X GET http://127.0.0.1:5984/<db-name>/_design/<design-doc-name>/_view/byUserItemCat?key="determination"

答案 1 :(得分:1)

Cloudant的搜索以返回文档的粒度进行。您的索引功能可以对文档中item的所用类别编制索引,然后您的搜索将返回包含您提及的类别的item的文档。然后,您的应用程序代码需要过滤到item以返回客户端。

你的索引功能就像(从Wintamute无耻地抄袭):

if (!doc.items || doc.items.length === 0) return;
var item;
for (var i=0; i<doc.items.length; i++) {
  index("cat", doc.items[i].cat, {"index": "not_analyzed"});
}

另一种方法是,如果您真的希望能够获得物品,可以将物品分解成自己的文件。

然而,我是第二个(并且已经投票)Wintamute的回答,因为我同意建议的视图是这个特定情况下的最佳解决方案(通过cat查找和显示项目)。

答案 2 :(得分:1)

这实际上可以通过Cloudant搜索来完成。我有一个类似的问题,我需要解决。特别感谢Cloudant的Mike Bresslin的帮助。

function(doc){
    if (doc.items) {
        for (var n in doc.items) {
            if (doc.items[n].cat) {
               index("cat", doc.items[n].cat, { store : true });
            }
        }
    }
}

您可以在搜索中将其查询为:

?q=cat:hardwork OR cat:determination