首页 > 代码库 > couchDB视图
couchDB视图
视图是设计文档的一部分。
视图函数
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 couchdbserver = 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 couchdbserver = 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 = http://www.mamicode.com/{"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(<<\"_id\">>, Doc, null),\n Emit(V,{Doc})\nend.\n\n", "reduce": "%% Reduce Function\nfun(Keys, Values, ReReduce) -> length(Values) end." } }}
python实现
安装couchdb-python包:
pip install pycouchdborpip install -i http://simple.crate.io/ pycouchdborgit clone git://github.com/niwibe/py-couchdb.gitcd py-couchdbpython 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视图