IBM Cloud Docs
创建视图MapReduce

创建视图MapReduce

视图用于获取数据库中存储的数据。 在视图中,你可以使用还原函数、映射和还原函数,并存储视图定义。

进一步了解最简单视图、还原函数、映射和还原函数限制以及存储视图定义。 此外,还可以查看所提供的示例。 视图是使用JavaScript 编写的。

查看概念

视图是处理数据库中文档内容的机制。 视图可以有选择地过滤文件,加快内容搜索速度。 它可用于在将结果返回客户端之前对结果进行预处理。

视图只是在设计文档的 views 字段中定义的JavaScript函数。 当你使用视图时、 或者更准确地说,是使用视图运行查询时、 系统会将JavaScript函数应用到数据库中的每个文档。 观点可能很复杂。 您可以选择定义一组JavaScript函数来创建所需的整体视图。

查看索引分区类型

视图索引继承自 options.partitioned 的分区类型 字段。

一个简单的观点

最简单的视图形式是地图功能。 映射功能生成的输出数据代表了对数据库中存储的文档的分析(映射)。

例如 您可能想知道哪个用户完成了在线注册,并有经过验证的电子邮件可供联系。 您可以通过检查每个文档,并 查找文档中名为 "email_verified "的字段,并获取 "email "的值。 如果该字段存在且值为 true、 则表示用户已完成注册,您可以通过电子邮件与他们联系。 如果该字段不存在或其值不是 true、 则用户未完成注册。

在视图函数中使用 emit 函数可以很容易地生成一个列表。 以响应使用视图进行的查询。 列表由键和值对组成、 其中,键可帮助您识别特定文件,而值则可提供您想要的精确细节。 列表还包括元数据,如返回的 key:value 对的数量。

文件 _id 会自动包含在每个 key:value 配对结果记录中。 包括文件 _id,以便客户更轻松地使用结果。

查看使用地图功能创建简单视图的示例:

function(user) {
  if(user.email_verified === true) {
    emit(user.email, {name: user.name, email_verified: user.email_verified, joined: user.joined});
  }
}

请参阅示例数据,以演示简单视图示例:

[
    {
        "_id":"abc123",
        "name": "Bob Smith",
        "email": "bob.smith@aol.com",
        "email_verified": true,
        "joined": "2019-01-24T10:42:59.000Z"
    },
    {
        "_id":"abc125",
        "name": "Amelie Smith",
        "email": "amelie.smith@aol.com",
        "email_verified": true,
        "joined": "2020-04-24T10:42:59.000Z"
    }
]

请参阅运行简单视图查询后的响应示例:

{
  "total_rows": 2,
  "offset": 0,
  "rows": [
    {
      "id": "abc125",
      "key": "amelie.smith@aol.com",
      "value": {
        "name": "Amelie Smith",
        "email_verified": true,
        "joined": "2020-04-24T10:42:59.000Z"
      }
    },
    {
      "id": "abc123",
      "key": "bob.smith@aol.com",
      "value": {
        "name": "Bob Smith",
        "email_verified": true,
        "joined": "2019-01-24T10:42:59.000Z"
      }
    }
  ]
}

地图功能示例

在设计文档中定义视图时,也会根据关键信息创建索引。 索引的编制和使用大大提高了查阅、搜索或从视图中选择文件的速度。

下文将介绍使用简单键和复杂键编制索引以及还原函数。

您的索引功能是在内存受限的环境中运行的,在这种环境中,文档构成了环境中使用的内存的一部分。 您的代码堆栈和文档必须位于内存中。 我们限制文件的最大大小为 64 MB。

为字段编制索引

下面的 map 函数会检查对象是否有 name 字段、 如果有,则输出该字段的值。 通过该检查,您可以查询 name 字段的值。

请参阅索引字段的示例:

function(doc) {
  if (doc.name) {
    emit("name", doc.name);
  }
}

一对多关系的索引

如果传递给 emit 的对象有一个 _id 字段、 视图查询的 include_docs 设置为 true 时,将包含具有特定 ID 的文档。

查看索引一对多关系的示例:

function(doc) {
  if (doc.friends) {
    for (friend in doc.friends) {
      emit(doc._id, { "_id": friend });
    }
  }
}

复杂密钥

键值不仅限于简单的值。 您可以使用任意 JSON 值来影响排序。

当关键字是一个数组时、 视图结果可以按关键字的分段分组。 例如 如果键的形式是 [year, month, day]、 则结果可缩减为单个值或按年份缩减、 月 或天。

更多信息,请参阅 使用视图

减少功能

options.partitioned 设置为 true 的设计文档不能包含自定义JavaScript减少函数。 只允许使用内置减速器。

无减速机

设计文档中的视图定义可以不带 reduce 属性,表示不执行查询时聚合。

{
    "views": {
        "getVerifiedEmails": {
            "map": "function(user) { if(user.email_verified === true) { emit(user.email); } }"
        }
    }
}

上一个映射功能生成的二级索引仅适用于选择。 索引总是按键(发射函数的第一个参数)排序,在本例中为 user.email。 该视图非常适合通过已知的用户电子邮件或用户电子邮件地址范围来获取文档。

内置还原功能

出于性能考虑 内置了一些简单的还原功能。 只要有可能、 您必须使用这些函数之一,而不是编写自己的函数。

要使用内置函数,请 请将还原器名称输入设计文档中视图对象的 reduce 字段。

计数器

_count 减速器会对 MapReduce 视图的行进行计数,并可选择按不同键对计数进行分组。

{
    "views": {
        "teamCount": {
            "map": "function(doc) { if (doc.email_verified === true) { emit(doc.team, doc.name); } }",
            "reduce": "_count"
        }
    }
}

之前的 MapReduce 视图创建了一个以用户所属 team 为关键字的索引,但只包括已验证电子邮件地址的用户。 由于减速器是 _count,因此视图会输出视图中的行数,例如数据库中已验证用户的数量。

{"rows":[
{"key":null,"value":10010}
]}

通过添加 ?group=true,计数会按不同的键分组,因此数据库会按团队成员输出计数:

{"rows":[
{"key":"blue","value":1409},
{"key":"green","value":1439},
{"key":"indigo","value":1425},
{"key":"orange","value":1432},
{"key":"red","value":1414},
{"key":"violet","value":1443},
{"key":"yellow","value":1448}
]}

关闭缩放器后,同一视图可用于选择单个团队的成员 ?key="orange"&reduce=false&limit=5

{"total_rows":10010,"offset":4273,"rows":[
{"id":"783173e102613c78d02a2b3304001642","key":"orange","value":"Bethel Lusk"},
{"id":"783173e102613c78d02a2b3304001b40","key":"orange","value":"Ethyl Dionne"},
{"id":"783173e102613c78d02a2b3304009c66","key":"orange","value":"Fredda Hendrix"},
{"id":"783173e102613c78d02a2b330401800d","key":"orange","value":"Bibi Page"},
{"id":"783173e102613c78d02a2b3304018ae7","key":"orange","value":"Marylou Lavender-Milton"}
]}

总和减速器

_sum 减速器会累加 MapReduce 视图发射的数值。 视图的值可以是一个数字、一个数字数组或一个包含数值的对象。 考虑以下关于产品数据库的 MapReduce 定义:

{
    "views": {
        "productPrices": {
            "map": "function(doc) {  emit(doc.type, { price: doc.price, tax: doc.tax }); }",
            "reduce": "_sum"
        }
    }
}

视图以产品类型为键,值是一个包含两个值的对象:pricetax_sum 减速器会计算整个视图中 pricetax 值的总数:

{"rows":[
    {"key":null,"value":{"price":144.97, "tax":7.32}}
]}

通过在查询视图时添加 ?group=true,可根据唯一键(本例中为产品类型)对输出进行分组和求和:

{"rows":[
    {"key":"kitchen","value":{"price":14.99,"tax":1.14}},
    {"key":"garden","value":{"price":129.98,"tax":6.18}}
]}

减速器

_sum 减速器一样,_stats 减速器也处理数字、具有数值的对象或数字数组,返回计数、总和、最小值和最大值以及数值的平方和,这对计算方差或标准偏差非常有用:

{
    "views": {
        "salesByDate": {
            "map": "function(doc) { emit(doc.date, [doc.price, doc.tax]); }",
            "reduce": "_stats"
        }
    }
}

前面的定义是对数组中的数值进行统计计算,而数组中的数值将作为索引值发出。 这些值将以数组形式返回,其顺序与 map 函数中提供的顺序相同:

{"rows":[
    {"key":"2025-01-01","value":[
        {"sum":14.99,"count":1,"min":14.99,"max":14.99,"sumsqr":224.7001},
        {"sum":1.14,"count":1,"min":1.14,"max":1.14,"sumsqr":1.2995}
    ]},
    {"key":"2025-01-02","value":[
        {"sum":129.98,"count":2,"min":29.99,"max":99.99,"sumsqr":10897.4002},
        {"sum":6.18,"count":2,"min":1.62,"max":4.56,"sumsqr":23.418}
    ]}
]}

不同减速器的大致数量

与数字减速器 _sum_stats 根据索引值进行操作不同,_approx_count_distinct 减速器使用视图的_键_。 它使用一种算法估算在 MapReduce 视图中找到的不同键的数量,这种算法占用的内存远远少于精确计数不同键算法:

{
  "views": {
    "estimateIpCount": {
      "map": "function (doc) {\n  emit(doc.ip, 1);\n}",
      "reduce": "_approx_count_distinct"
    }
  }
}

前面的视图定义旨在估算服务器日志数据库中不同 IP 地址的数量。 文档的 ip 将作为索引的_键_发送,以便 _approx_count_distinct 减法器能估算出不同键的数量:

{"rows":[
{"key":null,"value":100528}
]}

顶部/底部减速器

_top_x_bottom_x 减速器(其中 x 是一个介于 1 到 100 之间的数字)分别返回视图分组中顶部 x 或底部 x _值_的数组。 例如,在游戏应用程序中,可以创建一个以用户 ID 为键值的视图,其值就是用户取得的分数。 该视图可用于创建最佳或最差分数的记分牌:

{
    "views": {
        "bestScores": {
            "map": "function(doc) { emit(doc.user_id, doc.score); }",
            "reduce": "_top_3"
        }
    }
}

如果我们不带任何参数查询视图,则会返回整个视图中的前三名分数:

{"rows":[
  {"key":null,"value":[99,98,97]}
]}

通过分组 (?group=true),会返回每个不同用户的前三名得分:

{"rows":[
  {"key":"user082","value":[99,98,97]},
  {"key":"user291","value":[85,72,42]},
  {"key":"user452","value":[55,51,30]}
]}

第一个/最后一个减速器

_first/_last 还原器会分别返回视图分组中第一个或最后一个_键_的_值_。 如果我们有一个 IoT 应用程序,定期存储来自许多设备的读数,我们可以创建一个视图,以设备 ID 和读数时间为关键字。 视图的_值_是整个文档:

{
    "views": {
        "latestReading": {
            "map": "function(doc) { emit([doc.deviceid, doc.timestamp], doc); }",
            "reduce": "_last"
        }
    }
}

该视图生成这种形式的键和值,视图按 deviceidtimestamp 排序。 每个设备的“首次”和“最后”读数行都突出显示:

一读 ( group_level=1 ) 最后一次阅读 ( group_level=1 )
["A00","2025-01-01T10:00:00.000Z"] {"_id": "A00:5000","reading": 65,"timestamp":2025-01-01T10:00:00.000Z","deviceid":"A00"} x
["A00","2025-01-01T10:01:00.000Z"] {"_id": "A00:5001","reading": 64,"timestamp":2025-01-01T10:01:00.000Z","deviceid":"A00"}
["A00","2025-01-01T10:02:00.000Z"] {"_id": "A00:5002","reading": 59,"timestamp":2025-01-01T10:02:00.000Z","deviceid":"A00"} x
["A01","2025-01-01T10:00:00.000Z"] {"_id": "A01:8000","reading": 12,"timestamp":2025-01-01T10:00:00.000Z","deviceid":"A01"} x
["A01","2025-01-01T10:01:00.000Z"] {"_id": "A01:8001","reading": 15,"timestamp":2025-01-01T10:01:00.000Z","deviceid":"A01"}
["A01","2025-01-01T10:02:00.000Z"] {"_id": "A01:8002","reading": 19,"timestamp":2025-01-01T10:02:00.000Z","deviceid":"A01"} x
["A02","2025-01-01T10:00:00.000Z"] {"_id": "A02:4000","reading": 55,"timestamp":2025-01-01T10:00:00.000Z","deviceid":"A02"} x
["A02","2025-01-01T10:01:00.000Z"] {"_id": "A02:4001","reading": 54,"timestamp":2025-01-01T10:01:00.000Z","deviceid":"A02"}
["A02","2025-01-01T10:02:00.000Z"] {"_id": "A01:4002","reading": 56,"timestamp":2025-01-01T10:02:00.000Z","deviceid":"A02"} x

使用 group_level=1 查询视图,使用 _last 还原器,将返回数据库中每个设备 ID 的最新读数:

{"rows":[
{"key":["A00"],"value":{"_id":"93117567370d41d091b8dd160a3adf3f","_rev":"1-bc05e93e592d5a5a18e240240b581a55","deviceid":"A00","reading":13.8986,"timestamp":"2025-03-26T04:44:08.917Z","status":"red"}},
{"key":["A01"],"value":{"_id":"c9f53ac9e4a8444487ed0eaa11dc1c78","_rev":"1-1fcf121c73db03e49bac4c1981518b19","deviceid":"A01","reading":59.8453,"timestamp":"2025-04-01T01:52:34.254Z","status":"green"}},
{"key":["A02"],"value":{"_id":"577b7108a8a1458f9a17194ed1da398a","_rev":"1-71d345a773ab31f35ceb998f3c107c41","deviceid":"A02","reading":2.6208,"timestamp":"2025-03-31T00:22:17.175Z","status":"green"}},
{"key":["A03"],"value":{"_id":"150839b1d363427496a4f4e2917b8b1d","_rev":"1-860a2ed5f1f48aa642495dfb21dff3ce","deviceid":"A03","reading":55.8677,"timestamp":"2025-03-22T10:15:57.890Z","status":"red"}},
{"key":["A04"],"value":{"_id":"d3317bdc1f7b4466ae6bf7a30ca9e328","_rev":"1-a58762532f6980ca5b06a8d01d113814","deviceid":"A04","reading":44.1822,"timestamp":"2025-03-23T10:56:10.639Z","status":"green"}},
{"key":["A05"],"value":{"_id":"946754d3762f44e297ca20d13bbceb5e","_rev":"1-41fa2bb3ef8782c90b28ee44628abeab","deviceid":"A05","reading":13.2874,"timestamp":"2025-03-27T13:59:04.723Z","status":"blue"}},
{"key":["A06"],"value":{"_id":"bbcd8a5c0ae948baae713a9fcb5262d5","_rev":"1-66883211ee20a0772374672aa175dc50","deviceid":"A06","reading":7.9525,"timestamp":"2025-04-01T15:13:04.305Z","status":"blue"}},
{"key":["A07"],"value":{"_id":"a600caccdb82400698b158ecebfaa6f2","_rev":"1-68975a8d7133a13c6cc8ae34d28ea1c6","deviceid":"A07","reading":89.4818,"timestamp":"2025-03-07T02:12:59.934Z","status":"blue"}},
{"key":["A08"],"value":{"_id":"be20bae911db4da685f891fd01e07d3a","_rev":"1-d69b559627cf01e80fe85ea2f54d2f4b","deviceid":"A08","reading":97.6739,"timestamp":"2025-03-29T13:46:31.689Z","status":"green"}},
{"key":["A09"],"value":{"_id":"96526e80f2ff48e89e9e42aa47abae24","_rev":"1-85e56901f7113d7d6ff8ba573c535eb3","deviceid":"A09","reading":26.1597,"timestamp":"2025-03-18T03:22:19.848Z","status":"blue"}}
]}

内置减速器汇总

内置还原功能
功能 描述
_count 生成特定键的行计数。 值可以是任何有效的 JSON。
_stats 生成一个 JSON 结构,其中包含总和、计数、最小值、最大值和平方和值。 所有数值必须是数字。
_sum 求一个键的所有值的总和。 数值必须是数字。
_approx_count_distinct 通过使用 HyperLogLog算法的一种变体,近似计算视图索引中不同键的数量。
_top_x/_bottom_x 以数组形式返回视图分组中顶部 x 或底部 x _值_的数组,其中 x 是介于 1 和 100 之间的数字。
_first/_last 分别返回每个视图组的最低或最高排序_键_的_值_。

自定义还原功能

大多数客户发现,内置的还原器足以对从 Map 函数输出的视图 key-value 对进行聚合。 不过,在特殊情况下,可以提供JavaScript还原函数,而不是内置还原器的名称。

与内置的还原器相比,自定义还原函数的运行速度要慢得多,而且更难维护,因此在编写自定义还原函数之前,请检查是否可以使用内置的还原器来满足使用需求。

还原函数按以下顺序传递三个参数:

  • keys
  • values
  • rereduce

如果视图具有自定义JavaScript还原函数、 将用于生成该视图的汇总结果。 还原函数传递一组中间值,并将它们合并为一个值。 还原函数必须接受 作为输入、 相应的 map 函数产生的结果、 以及 reduce 函数本身返回的结果。 后一种情况称为 "reduce"。

下面的示例对还原功能进行了说明。

请参阅下面的自定义还原函数示例:

function (keys, values, rereduce) {
  return sum(values);
}

还原函数必须处理两种情况:

  1. rereduce 为假时:

    • keys 是一个数组,其元素是 形式的数组,其中 是映射函数发出的键,标识了生成该键的文档 是 中各元素发出的值的数组,例如:。[key, id] key id values keys reduce([ [key1,id1], [key2,id2], [key3,id3] ], [value1,value2,value3], false)
  2. rereduce 为真时:

    • keys 是。null
    • values 是一个数组,包含之前调用 reduce 函数返回的值,例如:。reduce(null, [intermediate1,intermediate2,intermediate3], true)

还原函数必须返回一个值、既适用于最终视图的 value 字段,也适用于传递给还原函数的 数组、和作为 values 数组的成员传递给还原函数。

通常情况下 通常情况下,可以编写 reduce 函数来处理还原调用,而不需要任何额外代码、 就像前面例子中的求和函数一样。 在这种情况下 rereduce 参数可以忽略。

通过将 reduce 函数的结果反馈到 reduce 函数中、 MapReduce可以将海量数据集的分析拆分成离散的并行任务,从而实现对数据的并行处理、 并行任务、 这样就能更快地完成任务。

使用内置 reduce 函数时,如果输入无效,将返回 builtin_reduce_error 错误。 返回错误信息。 reason 字段中提供了有关故障的更多详细信息。 导致错误的 会在 caused_by 字段中返回导致错误的原始数据。

请参见回复示例:

{
    "rows": [
        {
            "key": null,
            "value": {
                "error": "builtin_reduce_error",
                "reason": "The _sum function requires that map values be numbers, arrays of numbers, or objects. Objects can't be mixed with other data structures. Objects can be arbitrarily nested, if the values for all fields are themselves numbers, arrays of numbers, or objects.",
                "caused_by": [
                    {
                        "a": 1
                    },
                    {
                        "a": 2
                    },
                    {
                        "a": 3
                    },
                    {
                        "a": 4
                    }
                ]
            }
        }
    ]
}

映射和还原功能限制

这里描述了映射和还原函数的限制。

参考文献的透明度

映射函数必须是透明的。 参照透明意味着 表达式可以在不改变结果的情况下被替换为相同的值。 在本例中,是一个文档和一对 key-value。 因为参照透明、 IBM Cloudant视图可增量更新,并仅对上次更新后的 delta 进行重新索引。 增量更新,并仅对上次更新后的 delta 值进行重新索引。

交换和关联特性

除了参照透明外,还原函数还必须对输入具有交换和关联属性。 和关联属性。 这些属性使MapReduce 函数减少自己的输出并产生相同的响应:

f(Key, Values) == f(Key, [ f(Key, Values) ] )

因此,IBM Cloudant可以将中间结果存储到 结果存储到 B 树索引的内部节点。 这些限制 这些限制还使索引可以跨机器传播,并在查询时减少索引数量。 查询时间。

文件分区

由于存在分片,IBM Cloudant无法保证任何两个特定 map 函数的输出会传递到 同一个还原调用实例。 您不得依赖任何订购。 您使用的 您使用的 reduce 函数必须考虑传递给它的所有值,并返回正确的 IBM Cloudant 也保证在查询时通过 调用您的 reduce 函数,即使在查询时并不需要这样做。rereduce=true 函数,即使它在建立索引时并不需要这样做。建立索引时不需要这样做。 在这种情况下,您的函数必须能够正确工作。(rereduce=true 表示 keys 参数为 null,values 数组由之前的 reduce 函数调用结果填充)。是之前调用 reduce 函数的结果)。

减少数值大小

IBM Cloudant计算视图索引和相应的还原值,然后缓存。 然后将这些值缓存到 然后将这些值缓存到每个 B 树节点指针中。 现在, 在更新 BIBM Cloudant可以重复使用 在更新 B 树时重复使用已缩减的值。 您必须注意 还原函数返回的数据量。

返回数据集的大小最好保持在较小范围内,增长速度不超过 增长速度不超过 log(num_rows_processed)。 如果您忽略了这一限制、 IBM Cloudant不会自动出错、 但 B 树的性能 急剧下降。 如果您的视图在使用小数据集时工作正常,但在添加更多数据时却停止工作 视图可能违反了增长率特性限制。 特性限制。

执行环境

您的索引功能是在内存受限的环境中运行的,在这种环境中,文档构成了环境中使用的内存的一部分。 您的代码堆栈和文档必须位于内存中。 我们限制文件的最大大小为 64 MB。

options.partitionedtrue 时,没有JavaScript减速器

options.partitioned 设为 true 的设计文档不能包含JavaScript 还原函数,只能包含内置的 Erlang 还原器,如 _stats

存储视图定义

每个视图都是一个JavaScript函数。 视图存储在设计文档中。 所以、 来存储视图、 IBM Cloudant只需在设计文档中存储函数定义。 A design document can be 创建或更新 just like any other document.

存储视图定义 PUT 视图定义内容到 文档中。_design

在下面的示例中、getVerifiedEmails 视图被定义为地图功能、并可在设计文档的 views 字段中使用。

使用 PUT 方法将视图添加到设计文档中:

PUT $SERVICE_URL/$DATABASE/_design/$DDOC HTTP/1.1
Content-Type: application/json

下面的示例为 allusers 视图定义的设计文档添加了一个新的 getVerifiedEmails 名为视图的函数:

{
    "views": {
        "getVerifiedEmails": {
            "map": "function(user) { if(user.email_verified === true){ emit(doc.email, {name: user.name, email_verified: user.email_verified, joined: user.joined}) }}  "
        }
    }
}

请参阅申请示例:

curl -X PUT "$SERVICE_URL/users/_design/allusers" --data '{
  "views": {
    "getVerifiedEmails": {
      "map": "function(user) { if(user.email_verified === true){ emit(doc.email, {name: user.name, email_verified: user.email_verified, joined: user.joined}) }}"
    }
  }
}'
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.DesignDocument;
import com.ibm.cloud.cloudant.v1.model.DesignDocumentViewsMapReduce;
import com.ibm.cloud.cloudant.v1.model.DocumentResult;
import com.ibm.cloud.cloudant.v1.model.PutDesignDocumentOptions;

import java.util.Collections;

Cloudant service = Cloudant.newInstance();

DesignDocumentViewsMapReduce emailViewMapReduce =
    new DesignDocumentViewsMapReduce.Builder()
        .map("function(user) { if(user.email_verified === true){ emit(doc.email,{name: user.name, email_verified: user.email_verified, joined: user.joined}) }")
        .build();

DesignDocument designDocument = new DesignDocument();
designDocument.setViews(
        Collections.singletonMap("getVerifiedEmails", emailViewMapReduce));

PutDesignDocumentOptions designDocumentOptions =
    new PutDesignDocumentOptions.Builder()
        .db("users")
        .designDocument(designDocument)
        .ddoc("allusers")
        .build();

DocumentResult response =
    service.putDesignDocument(designDocumentOptions).execute()
        .getResult();

System.out.println(response);
import { CloudantV1 } from '@ibm-cloud/cloudant';

const service = CloudantV1.newInstance({});

const emailViewMapReduce: CloudantV1.DesignDocumentViewsMapReduce = {
  map: 'function(user) { if(user.email_verified === true){ emit(doc.email, {name: user.name, email_verified: user.email_verified, joined: user.joined}) }}'
}

const designDocument: CloudantV1.DesignDocument = {
  views: {'getVerifiedEmails': emailViewMapReduce}
}

service.putDesignDocument({
  db: 'users',
  designDocument: designDocument,
  ddoc: 'allusers'
}).then(response => {
  console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1

service = CloudantV1.new_instance()

email_view_map_reduce = DesignDocumentViewsMapReduce(
  map='function(user) { if(user.email_verified === true){ emit(doc.email, {name: user.name, email_verified: user.email_verified, joined: user.joined}) }}'
)

design_document = DesignDocument(
  views={'getVerifiedEmails': email_view_map_reduce}
)

response = service.put_design_document(
  db='users',
  design_document=design_document,
  ddoc='allusers'
).get_result()

print(response)
emailViewMapReduce, err := service.NewDesignDocumentViewsMapReduce(
  "function(user) { if(user.email_verified === true){ emit(doc.email, {name: user.name, email_verified: user.email_verified, joined: user.joined}) }}",
)
if err != nil {
  panic(err)
}

designDocument := &cloudantv1.DesignDocument{
  Views: map[string]cloudantv1.DesignDocumentViewsMapReduce{
    "getVerifiedEmails": *emailViewMapReduce,
  },
}

putDesignDocumentOptions := service.NewPutDesignDocumentOptions(
  "users",
  "allusers",
  designDocument,
)

documentResult, _, err := service.PutDesignDocument(putDesignDocumentOptions)
if err != nil {
  panic(err)
}

b, _ := json.MarshalIndent(documentResult, "", "  ")
fmt.Println(string(b))

前面的围棋示例需要以下导入块:

import (
  "encoding/json"
  "fmt"
  "github.com/IBM/cloudant-go-sdk/cloudantv1"
)

所有 Go 示例都要求 service 对象初始化。 有关更多信息,请参阅 API 文档中的 "身份验证 "部分 的示例。