一个CouchDB视图,每个“每个”返回一个元素;“集团”;

一个CouchDB视图,每个“每个”返回一个元素;“集团”;,couchdb,Couchdb,我的数据库中有大量如下所示的文档: { “_id”:“7fa2e319f3b908818d1c6eda9205fc6f”, “修订版”:“3-9DB3D8CC45C9A45B35C39381011E77BB5”, “Guid”:“2d69ba2e-972e-4659-8d3f-35f660229b6d”, “公司ID”:“foo”, “日期”:“2021-02-12T08:59:48Z”, “作者”:“我”, ... } CompanyId键出现在所有文档中,并且多个文档具有相同的Compan

我的数据库中有大量如下所示的文档:

{
“_id”:“7fa2e319f3b908818d1c6eda9205fc6f”,
“修订版”:“3-9DB3D8CC45C9A45B35C39381011E77BB5”,
“Guid”:“2d69ba2e-972e-4659-8d3f-35f660229b6d”,
“公司ID”:“foo”,
“日期”:“2021-02-12T08:59:48Z”,
“作者”:“我”,
...
}
CompanyId
键出现在所有文档中,并且多个文档具有相同的
CompanyId

我正在寻找一种方法来获取每个不同
CompanyId
值的最新
Date
文档。换言之,我需要一个文档数组,每个文档具有不同的
CompanyId

这是一对map/reduce:

功能(doc){
emit(doc.CompanyId,{doc:doc,date:date.parse(doc.date)});
}
函数(键、值、返回值){
var maxDate=0;
var maxDoc='';
对于(i=0;imaxDate){
maxDate=值[i]。日期;
maxDoc=值[i].doc;
}
}
返回{date:maxDate}
}
如果我将
group=true
传递给我的查询,上面的map/reduce对将按公司id成功返回最新文档的日期:

{
“行”:[
{
“密钥”:“a-testagency-556049-0897”,
“价值”:{
“日期”:1613123486000
}
},
{
“密钥”:“a-testagency-556677-1317”,
“价值”:{
“日期”:1613123435000
}
}
]
}
但我想要的不仅仅是结果中的日期,我想要文档本身,所以我将最后一行更改为:

return{date:maxDate,doc:maxDoc}
不幸的是,这会引发以下错误:

“减少输出必须更快地收缩:输入大小:37325输出大小:37233”

是否因为某些公司ID只有一个匹配的文档

如果我再次将返回线更改为较小的值:

return{date:maxDate,companyId:maxDoc.Author}

然后,查询现在返回
null
作为值,而不是日期和作者。

最后的代码片段使用PockDB演示了实现所需结果的一种方法(在少数方法中)。这是一个非常简单的解决方案,但结果是从2个请求而不是1个请求中获得的

要了解其工作原理,请查看CouchDB文档中的,特别是关于
rereduce
。这里的一篇深入的文章只是对该文档的重新整理

这是演示片段中的设计文档

{
    "_id": "_design/SO-66173759",
    "views": {
      "most_recent": {
        "map": `function (doc) {             
           if(doc.CompanyId && doc.Date) {                         
              emit([doc.CompanyId,doc.Date],doc._id);
           }
        }`,
        "reduce": `function(keys,values,rereduce) {               
           return values[0];
        }`
      }
    }
  }
emit生成复杂键[companyId,Date],value=document\u id。例如:

[Acme Amalgamated,2012-07-26T18:57:12.409Z]   7fb19b37-5baa-4c78-b122-fd0bc67253d0
[Acme Amalgamated,2013-08-16T02:53:12.062Z]   93d480a5-a666-4fca-b4a4-c1ba7935de92
[Acme Amalgamated,2013-08-23T22:12:14.401Z]   96a236b1-50d6-4b7e-af45-d05432ca7847
[Acme Amalgamated,2015-05-20T13:17:21.500Z]   ad55f6e7-6c61-4793-a75c-9601debd5eaf
[Acme Amalgamated,2015-12-17T09:18:33.741Z]   cf1a0844-aa54-42e2-a9d6-16e80f5c420a
[Acme Amalgamated,2016-08-24T04:01:15.551Z]   0658a417-901f-4cc7-a005-c10c72d2720c
[Acme Amalgamated,2020-06-19T07:58:44.680Z]   56126238-496a-475e-9001-8a4a86e055a3 **
[Cyberdyne Systems,2012-02-02T17:07:30.692Z]    d8a2b649-10b0-467b-b7e1-304b13f7560a
[Cyberdyne Systems,2012-05-31T17:47:15.607Z]    64699ddb-e8f5-449f-b1cb-804ccddbbfb2
[Cyberdyne Systems,2012-07-11T13:08:00.879Z]    1aa285f4-dc4b-49e4-9f0b-331b3d552dad
[Cyberdyne Systems,2014-08-12T22:43:47.651Z]    f5597fb0-e37e-4a62-8ef2-244140b0439b
[Cyberdyne Systems,2015-03-25T04:54:40.459Z]    c80f58d3-9fb1-466f-9fd2-2b3f86331fc3
[Cyberdyne Systems,2017-08-13T02:42:49.530Z]    c2b2d636-b444-4216-9b0b-e982ea467e51 **
[Lorem Ipsum Inc.,2010-01-26T21:31:34.752Z]   d6e2b66d-286f-48b9-b678-7afeca2c3c01
[Lorem Ipsum Inc.,2012-07-04T02:29:20.509Z]   c7d528fe-ce4f-4c35-a054-39f726962b4a
[Lorem Ipsum Inc.,2012-10-26T01:21:11.765Z]   773af027-1fdd-4f41-b1b1-8d5169871684
[Lorem Ipsum Inc.,2012-12-15T22:27:12.999Z]   78d60df3-aed6-4cab-8071-4d08ccfd0184
[Lorem Ipsum Inc.,2014-11-04T02:03:49.328Z]   098f600c-8059-44d5-a526-b67f0bbeb609
[Lorem Ipsum Inc.,2017-04-30T14:54:17.967Z]   639ddd9c-9a41-42fd-b1be-7fea8eb4f3ec
[Lorem Ipsum Inc.,2017-11-21T10:45:53.152Z]   ee2a7445-276d-4e9c-9f9d-1fa76d87741f **
**companyId组中的最新文档

通常,发出文档。_id是多余的,因为视图查询返回文档_id-但是在这种情况下,有一个很好的理由这样做,这将在后面很明显

密切关注索引的排序方式;在每个公司组中,最近日期是companyId组的最后一个条目

现在使用简洁的reduce函数

function(keys,values,rereduce) { return values[0]; }
使用以下参数将产生令人满意的结果

{
   reduce: true,
   group_level: 1,
   descending: true
}
{
  include_docs: true,
  keys: [
   "ee2a7445-276d-4e9c-9f9d-1fa76d87741f",
   "c2b2d636-b444-4216-9b0b-e982ea467e51",
   "56126238-496a-475e-9001-8a4a86e055a3"
  ]
}
递减
属性是这里的杀手,因为
减少
函数将以相反的顺序接收键和值;通过返回第0个值元素,
reduce
将始终根据日期字段生成最新的文档id,即使
reduce=true

给定前面的示例视图,使用上述参数访问视图将返回以下键/值行

[Lorem Ipsum Inc.]    ee2a7445-276d-4e9c-9f9d-1fa76d87741f    
[Cyberdyne Systems]   c2b2d636-b444-4216-9b0b-e982ea467e51
[Acme Amalgamated]    56126238-496a-475e-9001-8a4a86e055a3
在这里,它使用具有以下参数的值(文档ID)调用
\u all_docs

{
   reduce: true,
   group_level: 1,
   descending: true
}
{
  include_docs: true,
  keys: [
   "ee2a7445-276d-4e9c-9f9d-1fa76d87741f",
   "c2b2d636-b444-4216-9b0b-e982ea467e51",
   "56126238-496a-475e-9001-8a4a86e055a3"
  ]
}
将返回按companyId区分的最新日期的文档

这里有一个演示片段。该代码生成20个随机文档并生成压缩视图数据

重要
请务必了解,扫描整个索引是为了查找无约束的reduce。如果您的索引包含数百万个文档,那么可能需要一种更复杂的方法,例如利用开始/结束键或与提要相关的有趣内容。YMMV

异步函数视图\u reduce(){
let result=await db.query('SO-66173759/最近'{
是的,
组别级别:1,
下降:对
});
//展示
gel('view_reduce').innerText=result.rows.map(row=>`${row.key}\t${row.value}').join('\n');
返回结果;
}
异步函数showMostRecentDocs(){
//使用reduce的结果获取文档
让结果=等待视图_reduce();
//结果行值是文档ID;使用allDocs获取文档
结果=等待db.allDocs({
包含文档:true,
键:result.rows.map(row=>row.value)
});
//展示
gel('view_most_recent')。innerText=result.rows.map(row=>[row.doc.CompanyId,row.doc.Date,row.doc.Author]。join('\t'))。join('\n');
}
异步函数showViewKeyValues(){
let result=await db.query('SO-66173759/最近'{
减少:错,
包含文档:false
});
//展示
gel('视图\键\值')。innerText=
result.rows.map(row=>`[${row.key}]\t${row.value}`)。join('\n');
}
异步函数showViewDocs(){
let result=await db.query('SO-66173759/最近'{
减少:错,
包含文档:true
});
//展示
gel('view_docs')。innerText=result.rows.map(row=>[row.doc.CompanyId,row.doc.Date,row.doc.Author]。join('\t')).join('\n');
}
函数getDocsToInstall(计数){
常量sourceDocs=[{
“公司ID”:“Acme合并”,
“作者”:“Wile E.Coyote”,
},
{
“公司ID”:“Acme合并”,
“作者”:“路R.Unner”,
},
{
“公司ID”:“Lorem Ipsum公司”,
“作者”:“凯撒·奥古斯都”,
},
{
“公司ID”:“Lorem Ipsum公司”,
“作者”:“Marcus Aurelius”,
},
{
“公司ID”:“赛博达因系统”,
“作者”:“迈尔斯·戴森”,
}
];
//设计文件
常数ddoc={
“\u id”:“\u设计/