CouchDB-搜索,排序和汇总文档

问题描述 投票:0回答:1

我是不是沙发沙发新手,所以...

我有一个具有两种不同文档类型的数据库:

{
  "id": "1",
  "type": "User",
  "username": "User 1"
}

和具有以下结构的第二种文档类型:

{
  "id": "2",
  "type": "Asset",
  "name": "Asset one",
  "owner_id": "1"  //id of the user who owns the asset
}

我们需要显示现有资产列表和所有者名称(并排显示)。通过使用视图和链接文档,我们能够实现这一目标。问题是,现在我们需要能够对视图不支持的内容进行搜索和排序。

我们正在尝试使用CouchDB实现什么?我们可以使用搜索索引来做到这一点吗?

编辑:我们正在使用CouchDB 2.3.1,并且我们无法升级(至少目前为止)

编辑:我需要搜索username和资产name,并且还可以通过这些字段进行排序。我们不需要全功能搜索。像matches(不区分大小写)之类的东西就足够了。

编辑:在示例中指定的id / owner_id,代表文档_id。用户拥有的资产不得超过10个。正常情况下将是2/3资产。

couchdb
1个回答
0
投票

[如果不知道资产文档的完整性质(例如寿命,不变性等),可能会使您朝着积极的方向前进。问题似乎是,需要两个文档中的信息才能生成有意义的视图,这是没有发生的。

假设资产名称是不可变的,并且每个用户的资产数量很少,请考虑通过在用户文档中保留资产列表来对owner_id关系进行解耦和规范化。

例如,一个用户文档,其中assets属性包含一组拥有的资产文档信息(_id,名称):

{
  "_id": "1",
  "type": "User",
  "username": "User 1",
  "assets": [
    [
      "2",
      "Asset one"
    ],
    [
      "10",
      "Asset ten"
    ]
  ]
}

鉴于此结构,资产文档相当薄

{
  "_id": "2", 
  "type": "Asset",
  "name": "Asset one"
}

我认为资产文档中的信息比提供的要多。

那么如何获得搜索和排序结果?考虑具有以下映射功能的设计文档_design/user/_view/assets

function (doc) {
  if(doc.type === "User" && doc.assets) {
    for(var i = 0; i < doc.assets.length; i++) {
      /* emit user name, asset name, value as asset doc id */
      emit(doc.username + '/' + doc.assets[i][1], { _id: doc.assets[i][0] });
      /* emit asset name with leading /, value as User doc _id */
      emit('/' + doc.assets[i][1], { _id: doc._id })
    }
  }
}

假定数据库仅具有一个用户“用户1”和两个资产文档“资产一”和“资产十”。

此查询(使用cUrl)

curl -G <db endpoint>/_design/user/_view/assets

收益率

{
  "total_rows":4,"offset":0,"rows":[
    {"id":"1","key":"/Asset one","value":{"_id":"1"}},
    {"id":"1","key":"/Asset ten","value":{"_id":"1"}},
    {"id":"1","key":"User 1/Asset one","value":{"_id":"2"}},
    {"id":"1","key":"User 1/Asset ten","value":{"_id":"10"}}
  ]
}

不太有趣,除了注意行根据其key以升序返回。要颠倒顺序,只需添加descending=true参数

curl -G <db endpoint>/_design/user/_view/assets?descending=true

收益率

{
  "total_rows":4,"offset":0,"rows":[
    {"id":"1","key":"User 1/Asset ten","value":{"_id":"10"}},
    {"id":"1","key":"User 1/Asset one","value":{"_id":"2"}},
    {"id":"1","key":"/Asset ten","value":{"_id":"1"}},
    {"id":"1","key":"/Asset one","value":{"_id":"1"}}
  ]
}

现在这是凉爽的地方,那些凉爽的地方是startkeyendkey

对于键的性质,我们可以查询“用户1”的所有资产,并利用资产中的斜杠根据资产名称以有序的方式返回资产文档

 curl -G <db endpoint>/_design/user/_view/assets 
 -d "startkey="""User%201/"""" -d "endkey="""User%201/\uFFF0""""

请注意,我在Windows上,必须在其中使用双引号;(

收益率

{
  "total_rows":4,"offset":2,"rows":[
    {"id":"1","key":"User 1/Asset one","value":{"_id":"2"}},
    {"id":"1","key":"User 1/Asset ten","value":{"_id":"10"}}
  ]
}

这是前缀搜索。请注意,使用高位Unicode字符\ uFFF0作为终止符;我们要求视图中所有以“用户1 /”开头的文档。

类似地获得所有资产的排序列表

curl -G <db endpoint>/_design/user/_view/assets -d "startkey="""/"""" -d "endkey="""/\uFFF0""""

收益率

{
  "total_rows":4,"offset":0,"rows":[
    {"id":"1","key":"/Asset one","value":{"_id":"1"}},
    {"id":"1","key":"/Asset ten","value":{"_id":"1"}}
  ]
}

由于发出了资产文档_id,请使用include_docs来获取资产文档:

 curl -G <db endpoint>_design/user/_view/assets -d "include_docs=true"  
 -d "startkey="""User%201/"""" -d "endkey="""User%201/\uFFF0""""

收益率

{
  "total_rows": 4,
  "offset": 2,
  "rows": [
    {
      "id": "1",
      "key": "User 1/Asset one",
      "value": {
        "_id": "2"
      },
      "doc": {
        "_id": "2",
        "_rev": "2-f4e78c52b04b77e4b5d2787c21053155",
        "type": "Asset",
        "name": "Asset one"
      }
    },
    {
      "id": "1",
      "key": "User 1/Asset ten",
      "value": {
        "_id": "10"
      },
      "doc": {
        "_id": "10",
        "_rev": "2-30cf9245b2f3e95f22a06cee6789d91d",
        "type": "Asset",
        "name": "Asset 10"
      }
    }
  ]
}

对于发出用户_id的资产也一样。

注意

主要的缺点这里是删除资产文档需要更新用户文档;不是世界末日,但避免这种依赖将是非常好的。

鉴于资产与用户之间的原始1-1关系,完全摆脱资产文档,而仅将所有资产数据与用户文档一起存储可能是可行的,并且会大大降低复杂性。]

我希望以上内容能启发解决方案。祝你好运!

© www.soinside.com 2019 - 2024. All rights reserved.