视图函数

map函数

Map方法的参数只有一个,就是当前的文档对象。Map方法的实现需要根据文档对象的内容,确定是否要输出结果。 如果需要输出的话,可以通过emit来完成。 emit方法有两个参数,分别是key和value,分别表示输出结果的键和值。 使用什么样的键和值应该根据视图的实际需要来确定。 emit函数可以在map函数里被调用多次,创建一个文档的多个记录。

当希望对文档的某个字段进行排序和过滤操作的时候,应该把该字段作为键(key)或是键的一部分; value的值可以提供给 Reduce 方法使用,也可能会出现在最终的结果中。 可以作为键的不仅是简单数据类型,也可以是任意的 JSON 对象。比如emit([doc.title, doc.price], doc)中,使用数组作为键。

map函数示例(javascript代码):

function(doc) {

emit(doc._id, doc);

}

reduce函数

Reduce方法的参数有三个:key、values和rereduce,分别表示键、值和是否是rereduce 。 由于rereduce情况的存在,Reduce 方法一般需要处理两种情况:

传入的参数rereduce的值为false

这表明Reduce方法的输入是 Map方法输出的中间结果。

参数key的值是一个数组,对应于中间结果中的每条记录。 该数组的每个元素都是一个包含两个元素的数组,第一个元素是在Map方法中通过emit输出的键(key),第二个元素是记录所在的文档 ID 。

参数values的值是一个数组,对应于 Map 方法中通过emit输出的值(value)。

传入的参数rereduce的值为true

这表明Reduce方法的输入是上次Reduce方法的输出。

参数key的值为null。

参数values的值是一个数组,对应于上次Reduce方法的输出结果。

reduce函数示例(javascript代码):

function (key, values, rereduce) {

return sum(values);

}

实例解析

1、创建数据库testdb2,添加如下文档 :

{

"_id": "ef3c0dddfd988a9fa5dd77452a46a5e6",

"phoneNumber": "1001",

"billSeconds": 180,

"timestamp": "201408251705"

}

{

"_id": "ef3c0dddfd988a9fa5dd77452a482dd0",

"phoneNumber": "1001",

"billSeconds": 100,

"timestamp": "201408251715"

}

上述是分机1001的两条CDR,记录了两次通话的billSeconds,如果要计算通话时长,需要将 phoneNumber作为key,billSeconds作为value进行map和reduce操作。

2、用map操作过滤数据

function(doc) {

emit(doc.phoneNumber, doc.billSeconds);

}

map函数以phoneNumber参数作为key,以billSeconds作为value对数据库执行过滤操作。

3、用reduce计算结果

function (key, values, rereduce)

{

return sum(values);

}

reduce函数执行聚合操作,将key相同的value进行求和。

完整view创建代码如下:

{

"_id": "_design/jsTest",

"language": "javascript",

"views": {

"all": {

"map": "function(doc) {  emit(doc.phoneNumber, doc.billSeconds); }",

"reduce": "function (key, values, rereduce) {   return sum(values); }"

}

}

}

查询结果

单独执行map的结果:

curl http://127.0.0.1:5984/testdb2/_design/jsTest/_view/all?reduce=false

{"total_rows":2,"offset":0,"rows":[

{"id":"ef3c0dddfd988a9fa5dd77452a46a5e6","key":"1001","value":180},

{"id":"ef3c0dddfd988a9fa5dd77452a482dd0","key":"1001","value":100}

]}

map-reduce结果:

curl http://127.0.0.1:5984/testdb2/_design/jsTest/_view/all?group=true

{"rows":[

{"key":"1001","value":280}

]}

视图类别

临时视图

python示例:

import couchdb

server = couchdb.Server("http://192.168.131.121:5984")

db = server.create('python-tests')

db['johndoe'] = dict(type='Person', name='John Doe')

db['maryjane'] = dict(type='Person', name='Mary Jane')

db['gotham'] = dict(type='City', name='Gotham City')

map_fun = '''function(doc) {

if (doc.type == 'Person')

emit(doc.name, null);

}'''

for row in db.query(map_fun):

print(row.key)

del server['python-tests']

BigCouch不支持临时视图

永久视图

python示例:

import couchdb

server = couchdb.Server("http://192.168.131.121:5984")

db = server.create('python-tests')

db['johndoe'] = dict(type='Person', name='John Doe')

db['maryjane'] = dict(type='Person', name='Mary Jane')

db['gotham'] = dict(type='City', name='Gotham City')

viewData = {

"getdata":{

"map":"function(doc){ if (doc.type == 'Person') emit(doc.name, null);}"

}

}

db['_design/example'] = dict(language='javascript', views=viewData)

for row in db.view('example/getdata'):

print(row.key)

del server['python-tests']

视图实现语言

javascript实现

couchDB默认的查询语言是javascript,不需要进行配置即可使用js创建视图。

示例代码:

{

"_id": "_design/jsTest",

"language": "javascript",

"views": {

"all": {

"map": "function(doc) {  emit(doc._id, doc); }",

"reduce": "function (key, values, rereduce) {   return values.length; }"

}

}

}

erlang实现

编辑local.ini文件,添加如下配置:

[native_query_servers]

erlang = {couch_native_process, start_link, []}

配置后需要重启couchDB服务器。

示例代码:

{

"_id": "_design/erlangTest",

"language": "erlang",

"views": {

"all": {

"map": "%% Map Function\nfun({Doc}) ->\n  V = proplists:get_value(<>, Doc, null),\n  Emit(V,{Doc})\nend.\n\n",

"reduce": "%% Reduce Function\nfun(Keys, Values, ReReduce) -> length(Values) end."

}

}

}

python实现

安装couchdb-python包:

pip install pycouchdb

or

pip install -i http://simple.crate.io/ pycouchdb

or

git clone git://github.com/niwibe/py-couchdb.git

cd py-couchdb

python setup.py install

编辑local.ini文件,添加如下配置:

[query_servers]

python=/usr/bin/couchpy

配置后需要重启couchDB服务器。

示例代码:

{

"_id": "_design/pythonTest",

"language": "python",

"views": {

"all": {

"map": "def fun(doc):\n    yield doc['_id'],doc\n",

"reduce": "def fun(key, values, rereduce):\n    return len(values)\n"

}

}

}

视图的使用

运行视图的可选参数

key         限定结果中只包含键为该参数值的记录。

startkey    限定结果中只包含键大于或等于该参数值的记录。

endkey      限定结果中只包含键小于或等于该参数值的记录。

limit       限定结果中包含的记录的数目。

descending  指定结果中记录是否按照降序排列。

skip        指定结果中需要跳过的记录数目。

group       指定是否对键进行分组。

reduce      指定reduce=false可以只返回 Map 方法的运行结果。

示例数据:

{

"_id": "ef3c0dddfd988a9fa5dd77452a46a5e6",

"phoneNumber": "1001",

"billSeconds": 180,

"timestamp": "201408251705"

}

{

"_id": "ef3c0dddfd988a9fa5dd77452a482dd0",

"phoneNumber": "1001",

"billSeconds": 100,

"timestamp": "201408251715"

}

{

"_id": "ef3c0dddfd988a9fa5dd77452a63a9e3",

"phoneNumber": "1002",

"billSeconds": 180,

"timestamp": "201408251735"

}

{

"_id": "5fecc0d7fe5acac6b46359b5eec4f3ff",

"phoneNumber": "1003",

"billSeconds": 190,

"timestamp": "201408261035"

}

{

"_id": "_design/jsTest",

"language": "javascript",

"views": {

"all": {

"map": "function(doc) {  emit(doc.phoneNumber, doc.billSeconds); }",

"reduce": "function (key, values, rereduce) {return sum(values); }"

}

}

}

查找单个文档

语法:

/database/_design/designdocname/_view/viewname?key="${key}"

示例:

curl "http://192.168.131.121:5984/testdb2/_design/jsTest/_view/all?group=true&key=\"1001\""

{"rows":[

{"key":"1001","value":280}

]}

查找多个文档

语法:

/database/_design/designdocname/_view/viewname?startkey="${startkey}"&endkey="${endkey}"

示例:

curl "http://192.168.131.121:5984/testdb2/_design/jsTest/_view/all?group=true&startkey=\"1001\"&endkey=\"1002\""

{"rows":[

{"key":"1001","value":280},

{"key":"1002","value":180}

]}

curl "http://192.168.131.121:5984/testdb2/_design/jsTest/_view/all?group=true&startkey=\"1001\""

{"rows":[

{"key":"1001","value":280},

{"key":"1002","value":180},

{"key":"1003","value":190}

]}

curl "http://192.168.131.121:5984/testdb2/_design/jsTest/_view/all?group=true&endkey=\"1002\""

{"rows":[

{"key":"1001","value":280},

{"key":"1002","value":180}

]}

一般的关系数据库只要数据的结构是正确的,就允许运行任何的查询操作,同样的,CouchDB使用事先定义好的Map和Reduce函数以Map/Reduce的方式来进行查询。这些函数为用户提供了极大的灵活性,由于每一个文档都可以单独、并行地进行计算,所以它们可以适应不同的文档结构和索引[2]。CouchDB将一个Map函数和一个Reduce函数结合在一起称之为视图。

CouchDB中的视图是用来获得开发者或当前程序想要的数据集的方式,而且是一种静态的数据查询方式[3]。视图很有用,在筛选数据库中的文档,为某个特殊的程序找到相关的文档;按照一定的顺序从数据库的文档中提取数据;按照某种需要的值为文档建立相应的索引等情况下都可以使用。总之,CouchDB中的视图所做的事情与关系数据库中的SQL查询所做的事情有许多类似之处,是开发应用程序,浏览数据库中的文档必不可少的工具。

在CouchDB中一般将视图称为MapReduce视图,一个MapReduce视图由两个JavaScript函数组成,一个是Map函数,这个函数必须定义;另一个是Reduce函数,这个是可选的,根据程序的需要可以进行选择性定义[3]。

详细介绍CouchDB的Map和Reduce执行过程之前,先了解一下Futon为我们提供的临时视图(Temporary View)。临时视图是Futon中的一个可以对视图进行调试的界面(见图),没有问题的函数可以保存在Design文档中形成固定的视图。为了了解Map和Reduce的过程,我们以建立一个数据库groups为例来进行讲解,如图所示。

在groups中我们添加三个文档作为示例,文档的内容分别如下:

{   "_id": "4c1168fca1d0ad9f69a1267b86000ed5",

"_rev": "1-283727dba699785809c18abc7eaedfcc",

"名称": "A小组",

"成员": [

"李刚",

"刘伟",

"赵小云"

],

"平均年龄": 23,

"所获荣誉": [

"卫生先进小组",

"文体先进小组",

"学习先进小组"

]

}

{   "_id": "4c1168fca1d0ad9f69a1267b86001c23",

"_rev": "2-42b7064413f6667f3c3cfc77dc0dd0de",

"名称": "B小组",

"成员": [

"张力",

"刘明"

],

"平均年龄": 22.5,

"所获荣誉": [

"学习先进小组",

"文体先进小组",

"卫生先进小组"

]

}

{   "_id": "4c1168fca1d0ad9f69a1267b86002695",

"_rev": "1-2d7bd5cff3806e3227fc9b48fa3b8cc8",

"名称": "C小组",

"成员": [

"刘明",

"杨丽",

"马晓雯",

"朱慧"

],

"平均年龄": 21,

"所获荣誉": [

"文体先进小组",

"学习先进小组"

]

}

在Map的步骤中,输入的文档会从原始的结构转换或者映射为新的key/value对。现在我们通过一个Map函数来完成对小组名称的查询。在临时视图中输入以下函数:

function(doc) {

if(doc.名称)

{

emit(doc.名称);

}

}

运行后得到如图11-9所示的结果。

可以看到我们查询到了所有小组的名称,同时也可以看到小组的名称的下面还有该文档的ID。还可以查询出所有小组中的所有人的姓名。

Map函数如下:

function(doc) {

if(doc.成员)

{

for(var i in doc.成员)

{

emit(doc.成员[i]);

}

}

}

该函数的运行结果如图11-10所示。

单击图11-10所示界面左上角的“key”按钮可以执行改变成员的姓名称的排序等操作。

现在来看看Reduce函数的执行过程。Reduce就是将执行Map函数后得到的key/value对削减为一个单个的值或一个数据集合,这个过程是可选择的,而Map函数的执行过程是一个视图所必需的。前面提到一个Map函数执行的过程会产生包含文档ID和key以及value的行,Reduce的输入则是这些由Map得到的key/value的值,而不是文档ID。执行Reduce函数过后,将会产生一个单独的对所有value的化简结果或一个基于key的所有分组的计算。分组(Grouping)的操作无法在Reduce函数中控制,它只能通过传递到视图中的参数来控制。

CouchDB本身包含了三个内嵌的Reduce函数,分别是:_count,_sum和_stats,它们的功能分别如表11-2所示。在大多数情况下,对于我们开发CouchDB的应用程序来说,它们基本上够用了。在这三个函数中,_sum和_stats仅仅会对数据的值进行化简,而_count函数可以对任何类型的值计数,当然也包括null类型的值。

表11-2  内嵌Reduce函数

函    数    输    出

_count    返回Map结果集中值的个数

_sum    返回Map结果集中数值的求和结果

_stats    返回Map结果集中数值的统计结果

内嵌的_count函数是开发程序的时候最常用的Reduce函数,由于该函数可以用来统计任何值的个数,包括null值,所以当Map函数中emit的value值略去不写的时候,也可以使用该函数。下面是一个示例。

Map函数:

function(doc) {

if(doc.成员)

{

for(var i in doc.成员)

{

emit(doc.成员[i]);

}

}

}

Reduce函数:

_count

程序运行的结果如图11-11所示。

内嵌函数_sum会返回一个Map函数输出的值的和,所以该函数要求所有求和的值均为数值类型。

Map函数:

function(doc) {

if(doc.成员)

{

for(var i in doc.成员)

{

emit(doc.成员[i] ,doc.平均年龄);

}

}

}

Reduce函数:

_sum

在“Grouping”下拉框中选择“exact”,则返回每个人对应的平均年龄。运行的结果如图11-12所示。

内嵌函数_stats返回一个JSON数据对象,该对象中包含sum、count、min、max、sumsqr的值,分别表示求和、计数、求最小值、求最大值、求和的平方。和_sum一样,该函数同样要求所有的参与运算的值均为数值类型。

Map函数:

function(doc) {

if(doc.成员)

{

for(var i in doc.成员)

{

emit(doc.成员[i] ,doc.平均年龄);

}

}

}

Reduce函数:

_stats

执行后的结果如图11-13所示。

在执行Map/Reduce的过程中,数据库中的每一个文档为Map函数的参数,该函数可以将所有的文档都忽略,或者通过emit()返回一行或者多行key/value对。除了文档之外Map函数几乎不依靠任何信息,正是这种执行的独立性,使得CouchDB视图可以大量、并行地产生。

CouchDB的视图按照键(key)的顺序进行排序并以行组(rows)的形式进行存储,因此即使按照多个键值在成百万、上千万的数据中进行检索也会具有很高的执行效率。所以,当编写Map函数的时候,首要的目标就是建立一个按照相似的键值来存储相关数据的索引。

虽然MapReduce的功能很强大,可以完成很多的工作,但它也有自己的局限性。在Map阶段产生的索引是一维的,这就意味着在Reduce的阶段不能产生大量的数据,否则会大大降低程序的性能。比如,CouchDB的MapReduce并不适于全文本检索和自组织搜索等应用,这类问题更适合用Lucene这样的工具来解决。此外,在CouchDB中处理地理信息数据也并不是很方便,如果需要处理地理信息数据,则最好使用CouchDB的一个分支系统GeoCouch。

couchdb 视图操作_couchDB视图相关推荐

  1. couchdb 视图操作_CouchDB 视图简介及增量更新视图的方法

    CouchDB 视图简介及增量更新视图的方法 郭 君, 高 云鹤, 和 林 宜谦 2016 年 4 月 18 日发布 简介 CouchDB 是一种 NoSQL 数据库,数据以 JSON 文档的形式存储 ...

  2. couchdb 视图操作_CouchDB的安装使用教程

    CouchDB的安装使用教程 Apache CouchDB通常简称为CouchDB的,是一个开放源码的数据库,侧重于易用性和完全拥抱网络"数据库". 这是一个NoSQL数据库,使用 ...

  3. couchdb 视图操作_CouchDB简单应用

    CouchDB是众多称作NoSQL解决方案中的一员.与众不同的是,CouchDB是一个面向文档的数据库,在它里面所有文档域(Field)都是以键值对的形式存储的.域(Field)可以是一个简单的键值对 ...

  4. couchdb 视图操作_CouchDB快速入门

    Apache CouchDB数据库,它类似于Redis,Cassandra和MongoDB,也是一个NoSQL数据库. CouchDB将数据存储为非关系性的JSON文档. 这使得CouchDB的用户可 ...

  5. 数据库之多表查询与视图操作

    步骤: 在上一次的基础上对已经创建的jwg数据库中的数据表进行各种查询操作 多表查询 1.进行多表查询 从student.course.student_course三个表中检索出学生的学号.姓名.学习 ...

  6. couchdb 视图操作_使用 Couchdb-python 操作 CouchDB

    使用 Couchdb-python 操作 CouchDB 郭 君, 高 云鹤, 和 林 宜谦 2015 年 12 月 28 日发布 简介 Couchdb-python 是目前最常用的操作 CouchD ...

  7. 2021年大数据HBase(十一):Apache Phoenix的视图操作

    全网最详细的大数据HBase文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 前言 Apache Phoenix的视图操作 一.应用场景 ...

  8. 建立计算机系学生视图,实验六 视图的操作.doc

    实验六 视图的操作 实验六 视图的操作 一.实验目的 1.理解的概念. .掌握.SQL语句创建视图,掌握查询分析器的使用 1.语句格式 CREATE VIEW [( [,]-)] AS [WITH C ...

  9. MySQL中的视图操作

    文章目录 1 为什么要使用视图 2 创建视图 3 查看视图 4 更新视图数据 5 修改视图 6 删除视图 1 为什么要使用视图 小学的时候,每年都会举办一次抽考活动,意思是从每一个班级里面筛选出几个优 ...

最新文章

  1. fileupload控件在ajax中无法使用
  2. phantomjs使用说明
  3. Hadoop实例之利用MapReduce实现日志清洗(附源代码)
  4. 高级数据结构与算法 | 哈希 :哈希冲突、负载因子、哈希函数、哈希表、哈希桶
  5. [js高手之路]从原型链开始图解继承到组合继承的产生
  6. 模拟退火总结+洛谷模板题(P1337 [JSOI2004]平衡点 / 吊打XXX)
  7. java怎么接收前端请求_前端json post 请求 后端怎么接收
  8. SQL Server遍历表(临时表)
  9. 兼容性测试之VMware
  10. 手动安装Linux网卡驱动程序
  11. 受半导体短缺及疫情影响,丰田已下调9月10月及当前财年产量预期
  12. 阿里巴巴:第四财季净亏损76.54亿元,主要由于反垄断法罚款
  13. python黑色背景白色背景_用Python去除图像的黑色或白色背景实例
  14. Django之--POST方法处理表单请求
  15. hive内部表和外部表的区别_3000字揭秘Greenplum的外部数据加载——外部表
  16. fft matlab代码,FFT的matlab程序代码
  17. 微信公众号迁移公证需要哪些材料?账号迁移流程来了
  18. 华为手机USB调试与Log
  19. 出现老是弹出Visual Studio 实时调试器 的问题
  20. APP推广重点渠道解析及我这些年踩过的坑

热门文章

  1. 涵盖18+ SOTA GAN实现,这个图像生成领域的PyTorch库火了
  2. 12.6%!IJCAI 2020接收率断崖式下跌,但还是有华人大佬中了三篇
  3. 推荐一位玩自动化的 Python 爱好者
  4. 再来一个吊打百度网盘的开源神器,还是99年妹子开发的
  5. 我在 GitHub 上发现了一款骚气满满的字体!
  6. Django项目配合sentry实现浅析
  7. 深度学习 | 三个概念:Epoch, Batch, Iteration
  8. OpenCV+Tensorflow实现实时人脸识别演示
  9. jQuery API之each、children、index的使用
  10. 步步为营 .NET 设计模式学习笔记 六、Adapter(适配器模式)