Indexing 如何创建和维护couchDB/pcouchDB doc#u id';s

Indexing 如何创建和维护couchDB/pcouchDB doc#u id';s,indexing,couchdb,pouchdb,Indexing,Couchdb,Pouchdb,我是couchDB的新手,我正试图用doc\u id的用法来表达我的想法。到目前为止,我读到并学到的是,我应该生成一个doc\u id,这样我就可以使用B-树进行索引/映射。建议使用的工具有Docuri或backdb/collate。 让一些代码自己说话: // define a docuri route Docuri.routes({ ':type/:name/:created_at': 'list' }); var doc = {};

我是couchDB的新手,我正试图用
doc\u id
的用法来表达我的想法。到目前为止,我读到并学到的是,我应该生成一个
doc\u id
,这样我就可以使用B-树进行索引/映射。建议使用的工具有Docuribackdb/collate。 让一些代码自己说话:

    // define a docuri route
    Docuri.routes({
        ':type/:name/:created_at': 'list'
    });

    var doc = {}; 
        doc.name = 'Testname_1';
        doc.type = 'List';
        doc.created_at = Math.floor(Date.now() / 1000);
        doc.updated_at = Math.floor(Date.now() / 1000);
        doc._id = Docuri.list(doc);

console.log(doc');
// {
//    _id: "list/Testname_1/1433973431"
//     created_at: 1433973431
//     name: "Testname_1"
//     type: "list"
//     updated_at: 1433973431
// }
接下来,我将为具有以下结构的列表添加一些项

    // define a docuri route
    Docuri.routes({
        '/:list_id/:type/:item/:created_at': 'item'
    });

    var doc = {}; 
        doc.item = 'Item_1';
        doc.type = 'Item';
        doc.list_id = 'List/Testname_1/1433973431';
        doc.created_at = Math.floor(Date.now() / 1000);
        doc.updated_at = Math.floor(Date.now() / 1000);
        doc._id = Docuri.item(doc);

console.log(doc');
// {
//    _id: "List/Testname_1/1433973431/Item/Item_1/1433973431"
//     list_id: "List/Testname_1/1433973431"
//     created_at: 1433973431
//     item: "Item_1"
//     type: "Item"
//     updated_at: 1433973431
// }
问题1 对于较小的数据库来说,这种结构好吗

问题2 (这让我非常恼火)假设我会使用列表
\u id
,就像
。现在,如果列表名称会更改,我是否也应该更改列表的
\u id
,然后更改相应项目中的所有
列表id

这对我来说似乎很奇怪,因为我通常不会更改数据库条目的ID

但另一方面,用户希望HMTL链接对应于他的新列表名

也许有人能把我推向正确的方向,如何管理和使用couchDB和PockDB中的
\u id

编辑

以下是我读到的关于UUID的两个教程

在决定使用随机值作为doc\u id之前,请阅读“何时不使用map reduce”一节

尽可能使用特定于域的文档ID。使用CouchDB时,最好使用有意义的ID

在本例中,每次将文档添加到数据库时,您都可以免费获得所有这些“索引”。与随机生成的UUID相比,它不会占用磁盘上的任何额外空间,而且您不必等待视图建立,也不必理解map/reduce API

当然,当您需要根据各种条件进行搜索时,该系统开始变得不稳定:例如,所有专辑按年份排序,艺术家按年龄排序,等等。您只能对字符串进行排序,而不能对数字、布尔值、数组或任意JSON对象进行排序,如map/reduce API支持。但是对于许多简单的应用程序,根本不需要使用query()API就可以了

性能提示:如果您只是使用随机生成的文档ID,那么您不仅错过了获取免费索引的机会,还将导致构建一个永远不会使用的索引的开销。因此,请使用和滥用您的文档ID


Docuri是一个有趣的想法,我完全支持CouchDB技巧和类似的“黑客”,但请不要被它误导。这是一个骗局,有点像“黑客”

我基本上只有几个文档ID的策略/习惯:

  • 它们是完全随机和无意义的(对于应用程序代码而言),尽管我经常在它们前面加上类型前缀,严格地说只是为了调试方便-任何需要知道文档类型的代码都是从
    doc.type
    或类似字段获得的,而不是从
    doc.\u id
    获得的。因此,我可能会将一个文档称为“photo-1qr333qew3qadeiof”,这样我就可以在web日志或其他内容中注意到它,但应用程序逻辑不会根据id假设任何内容
  • 有时我需要确保相关文档的唯一性,例如,“用户”文档可能需要一个(或至少不超过)相关的“概要文件”文档。或者,一个更好的例子,也许我想确保一个特定的交易只发生一次:避免重复购买或其他事情。因此,我获取一个用户id和内容id的“元组”,并通过
    'txn-'+散列(username+song.\u id)
    识别购买记录。然后,如果这个特定的组合意外地再次发生,我将得到一个409*,因为这个确定性派生的id
  • 更不常见的是,我有时会为某个应用程序制作特殊的ID(比如一个名为“共享配置”或“我的应用程序全局计数器”之类的文档),这样它就可以在有限的情况下出于特定目的直接访问它们
但关键是,默认情况下,您应该为文档使用某种UUID,除非您有充分的理由不这样做。CouchDB只在文档级别提供原子性这一事实意味着您可能会在文档id中增加一点含义(如第二种情况),并且还会看到Docuri之类的技巧,这些技巧使用id“优化”某些情况,但首先将它们视为“无意义但唯一的”字符串

通常使用视图根据文档中的数据创建有意义的[辅助]索引。(是的,同样,在特殊情况下,您可以通过
\u all\u docs
使用/滥用“主”索引,即数据库本身,作为优化/技巧/黑客,但这不是正常做法。)


[*在Cloudant和CouchDB 2.0下,正确处理最后一个案例更为复杂,因为这是一个不同的主题。]

我最终使用了两个助手脚本,并且

我的“列表”数据库中的条目现在有一个新字段
slug
。 首先,我使用speakingUrl从用户提供的列表名创建一个
slug
,然后使用docuri生成带有
slug
值的
\u id

docUri.routes({ ':type/:slug/:created_at': 'list' });

var slug = speakingUrl('My List Name is test');

var listObj = {};    
listObj.name = 'My List Name is test';
listObj.type = 'list';  
listObj.created_at = Math.floor(Date.now() / 1000);
listObj.updated_at = Math.floor(Date.now() / 1000);
listObj.slug = slug;  
listObj._id = docuri.list( listObj );
我的列表文档如下所示:

[
  {
    "id": "list/my-list-name-is-test/1436098113",
    "key": "list/my-list-name-is-test/1436098113",
    "value": {
      "rev": "1-d96c34ce1732e3e8088c4fa9d6e54c14"
    },
    "doc": {
      "name": "My List Name is test",
      "type": "list",
      "created_at": 1436098113,
      "updated_at": 1436098113,
      "slug": "my-list-name-is-test",
      "_id": "list/my-list-name-is-test/1436098113",
      "_rev": "1-d96c34ce1732e3e8088c4fa9d6e54c14"
    }
  }
]
[
  {
    "id": "item/my-list-name-is-test/This is the item Title/1436098113",
    "key": "item/my-list-name-is-test/This is the item Title/1436098113",
    "value": {
      "rev": "1-c023db010d075d6a9129288b0649554d"
    },
    "doc": {
      "Title": "This is the item Title",
      "type": "item",
      "created_at": 1436098113,
      "updated_at": 1436098113,
      "slug": "this-is-the-item-title",
      "_id": "item/my-list-name-is-test/This is the item Title/1436098113",
      "_rev": "1-c023db010d075d6a9129288b0649554d"
    }
  }
]
在p/couchDB
{startkey:'list',endkey:'list\uffff'}中按名称对列表进行排序

通过此设置,我可以使用列表URL的slug字段www.foo.bar/List/我的列表名为test。在目标页面上,我使用URL slug通过以下过滤器查询列表项

{startkey:'item/'+URL\u SLUG\u VAR,endkey:'item/'+URL\u SLUG\u VAR+'\uffff'}

我的项目文档如下所示:

[
  {
    "id": "list/my-list-name-is-test/1436098113",
    "key": "list/my-list-name-is-test/1436098113",
    "value": {
      "rev": "1-d96c34ce1732e3e8088c4fa9d6e54c14"
    },
    "doc": {
      "name": "My List Name is test",
      "type": "list",
      "created_at": 1436098113,
      "updated_at": 1436098113,
      "slug": "my-list-name-is-test",
      "_id": "list/my-list-name-is-test/1436098113",
      "_rev": "1-d96c34ce1732e3e8088c4fa9d6e54c14"
    }
  }
]
[
  {
    "id": "item/my-list-name-is-test/This is the item Title/1436098113",
    "key": "item/my-list-name-is-test/This is the item Title/1436098113",
    "value": {
      "rev": "1-c023db010d075d6a9129288b0649554d"
    },
    "doc": {
      "Title": "This is the item Title",
      "type": "item",
      "created_at": 1436098113,
      "updated_at": 1436098113,
      "slug": "this-is-the-item-title",
      "_id": "item/my-list-name-is-test/This is the item Title/1436098113",
      "_rev": "1-c023db010d075d6a9129288b0649554d"
    }
  }
]
当用户现在更改列表名称值时,
slug
应该保持不变,因此对项目的查询应该可以工作

此解决方案的缺点是,当用户更改列表名称时,
slug
不会更改