Couch db 浅漫游.

Post on 17-May-2015

1.212 views 1 download

Transcript of Couch db 浅漫游.

CouchDB 浅慢游

jinyuan@taobao.com

website with CouchDB

•http://www.elyservice.co.uk/ 这个个人网站使用 CouchDB的技术资料 http://www.jasondavies.com/blog/2009/05/08/couchdb-on-wheels/

•https://github.com/langalex/boom_amazing

•https://github.com/hpoydar/processing-js-studio

•https://github.com/quirkey/swinger

•https://github.com/jchris/couchdb-twitter-client

•https://github.com/langalex/boom_amazing

Boom Amazing

CouchDB Twitter Client

Let's give it a try on windows

How to install couchDB on windows

安装地址

How to install cygwin on windows( 辅助工具 )

安装地址

RESTful API

What is REST? See REST简介

• GET: retrieve data from the database

• PUT: insert new data and modify existing data

• POST: equate to put, but it is not recommended in most cases

• DELETE: delete data from the database

• COPY: copy documents in the database

标准的 HTTP 方法:

How to Creating your first database using the HTTP API

Creating the database is simple curl -X PUT http://127.0.0.1:5984/contacts

Get databases are currently available on the server curl -X GET http://127.0.0.1:5984/_all_dbs

delete special database on the server curl -X DELET http://127.0.0.1:5984/contacts

fetch some information about the contacts database curl -X GET http://127.0.0.1:5984/contacts

Creating doucuments in your Contacts Database

// 创建名字为 kevin 的文档curl -X PUT http://127.0.0.1:5984/contacts/kevin -d '{}‘

// 获取刚创建的文档curl -X GET http://127.0.0.1:5984/contacts/kevin

// 逻辑删除文档curl -X DELETE http://127.0.0.1:5984/contacts/kevin?rev=?

// 是不是逻辑删除我们可以重新激活它 , 在这个删除的版本上更新操作curl -X PUT http://127.0.0.1:5984/contacts/kevin -d '{"_rev":"?","email":["jinyuan@taobao.com","xiaoq@taobao.com"],"age":"23"}'

//copy 数据库(备份数据库)curl -X COPY http://127.0.0.1:5984/contacts/kevin -H "Destination: xiaoqiang"

Getting started with CouchDB views

查询详细的生存的文档视图 curl -X GET http://127.0.0.1:5984/contacts/_all_docs (?include_docs=true) 可选

how to get some meaningful data out of your CouchDB database, using the built-in JavaScript view engine.

Using views, you can aggregate and report on the documents in your CouchDB database

there is no restriction on the number of views you can have of any one document

视图本身就是一个特殊的文档

Traditional RDBMS BMM_USER table

you wanted to retrieve the name, e-mail address, and fax number of all your users

SELECT name, email, fax FROM BMW_USER

same data but in a CouchDB database

在进一步地了解视图之前,让我们先看个简单的 map 函数编写

If we wanted to know all the information for user "Alice" we would write a SQL query similar to the following:

SELECT * FROM users WHERE username = "Alice"

Getting started wit CouchDB views

let's translate this data into something that would make sense for CouchDB “Map function document”.

{ "type": "user", "username" : "Alice", "password" : "kittycat"}

the information for user “Alice” 的 JSON 数据结构

Let's write a very quick and dirty Map function that will allow us to lookup a user from our user documents based on username. The skeleton of a Map function is just a single Javascript function that takes a single argument of a document (JSON object).

function(doc){}

Map function

Firstly,let's add in the equivalent of the FROM clause. Since this function will be applied to every document in our system, including non-user documents, we'll need to distinguish which documents we will actually want to pull from.

function(doc){

if(doc.type == "user"){ //Now we know we have a user document}

}

Map function

Map function

Now let's add in the SELECT * and WHERE username = 'Alice' parts together

the key in our table will be the criteria we use to lookup the data we're interested in. Thus, we need to emit the user document's username as the key, and the entireDocument as the value.

function(doc){

if(doc.type == "user"){ emit( doc.username, doc );

//Map functions convert documents into a hash table-like structure, and that's what this function will need to do. It will perform this task through a function called emit

}} 这样一个简单 map 函数编写完成了

introduction to CouchDB views

Temporary viewfunction(doc) {

if(doc.fax && doc.name && doc.phone)emit(doc._id, {Name: doc.name, Phone: doc.phone});

}execute a temporary view ( 限制使用 )

curl -X POST http://127.0.0.1:5984/bmw_users/_temp_view -d '{"map":"function(doc) {emit(doc._id, doc); }"}' -H 'Content-Type:application/json’

execute a permanent viewcurl -X GET

http://127.0.0.1:5984/bmw_users/_design/users/_view/get_fax_users

curl -X GET

http://127.0.0.1:5984/bmw_users/_design/users/_view/get_email_users

当然我们可以合并这二个视图,如既要按 fax 或 email 查询用户,取这 2 个视图的并集curl -X GET http://127.0.0.1:5984/bmw_users/_design/users/_view/get_fax_or_email

有时候我们需要过滤文档,找到我们所关心的文档curl -X GET http://127.0.0.1:5984/bmw_users/_design/users/_view/get_name_users

浏览器查询

浏览器查询

浏览器查询

看个小例子

The raw view of the contacts database

http://127.0.0.1:5984/bmw_users/_design/users/_view/get_email_users( 页面输出标准的 json 格式,我们可以方便的 ajax来获取数据 )

如采用 YUI 封装的 ajax 写法, IE 下打开测试页面 http://zhengke.org/project/test/ajax.html 等待页面加载完成后直接获取数据渲染页面

浏览器查询

Map/Reduce

how CouchDB uses map/reduce views instead of SQL statements to interact with data ?

看图

如何归并相同的 key 数据? See Reduce Function

点击 Run 按钮执行

Reduce Function

function(key, values, reduce){}

we know the reduce function works after the map function,this reduce function will process data from the Map function'shash table.

"key" argument is a singular key from the hash table "value" is whatever we emitted as the value under that

particular key.

let's take a look at how a Reduce function could potentially change this hash table down into a different form of data.

the Reduce function is responsible for reducing the values under a particular key in the hash-table down into a smaller result set, potentially a single record.

Making the Map a little more useable with Reduce

One SQL comparison:

SELECT count(*) FROM users

Map for reducefunction(doc){

if(doc.type == "user"){emit( 1, doc );}

} Reduce counting users

function(key, values, rereduce){

return values.length;}

If we had 20 user records(documents), then the result would be {"1" : "20"}.

看图当我选中下图 reduce 这个选择框时,就归并了相同的 key 记录,我这里的归并函数是 sum 函数(注,按照自己的需求函数都可以自定义)

Reduce as a funnel that takes a view

这个函数的语义分析

•Contain both an e-mail address and a fax number•Contain only an e-mail address•Contain only a fax number•Contain neither an e-mail address nor a fax number

function(doc) {if(doc.email && doc.fax)

emit("Both", 1);else if(doc.email)

emit("Email", 1);else if(doc.fax)

emit("Fax", 1);else

emit("Neither", 1);}

Map/Reduce

how you can aggregate this data to produce a count of the contacts for each key.

The Reduce Function for the Aggregate View

function(key, values, reduce) {return sum(values);

}更新 doucument ,视图也会自动更新

// 查看视图curl -X GET http://127.0.0.1:5984/bmw_users/_design/users/_view/count_by_type

根据 key 分组curl -X GET http://127.0.0.1:5984/bmw_users/_design/users/_view/count_by_type?group=true

Map/Reduce vs. SQL Queries

SELECT id, name, email FROM contacts WHERE country = 'USA' ORDER BY name

function(doc) {if(doc.type != "contact") return;emit([doc.country, doc.name], {name: doc.name, email:

doc.email});}

http://127.0.0.1:5984/bmw_users/_design/users/_view/get_complex_key

http://127.0.0.1:5984/bmw_users/_design/users/_view/get_complex_key?startkey=["USA"]&endkey=["USA",{}]

SELECT COUNT(*), country FROM contacts GROUP BY country ===>

map: function(doc) {emit(doc.country, 1);

}reduce: function(key, values, rereduce) {

return sum(values);}

word count Example

http://127.0.0.1:5984/doucuments/_design/words/_view/count_word?group=true

usering Futon

让我们图形化管理,爽!告别 API , Codeing!

access Futon HomePage

http://127.0.0.1:5984/_utils

Create a database through Futon

Example JSON output of database statistics

http://localhost:5984/couchdb_in_action

Modeling data in documents

If SQL is based on a rigid type system enforced by tables, then CouchDB is best described as a ducktyped system. Ducktyping comes from the expression "if it looks like a duck, talks like a duck, then it's probablya duck."

{ "doc_type" : "Person", "name" : "Chris Chandler", "login" : "cchandler", "address" : "1234 N. Here St."}

look like a Person

• one-to-one

• one-to-many

• many-to-many

Transitioning more complex relationships to documentsThe three principal relationships

We know that JSON supports both objects(hashes) and arrays, so we know we can store arbitrarily

complex types within a document.

JSON

/* User */{"username" : "chris"}

/* Address */{"type" : "shipping""address1" : "1234 N. Here St.","city" : "Phoenix","state" : "Arizona","zip" : "85005""country" : "us"}

two relation document

we can easily perform by moving the entire contents of the address document underneath a key called "addresses" in the user document

document of merged one-to-many with type on the sub document

/* Combined document */{

"username" : "chris","addresses" : [{"type" : "shipping""address1" : "1234 N. Here St.","city" : "Phoenix","state" : "Arizona","zip" : "85005""country" : "us"}]

}

Combined document one to one

/* Combined document */

{ "username" : "chris","addresses" : { "shipping" : { "address1" : "1234 N. Here St.", "city" : "Phoenix", "state" : "Arizona", "zip" : "85005" "country" : "us" }, "billing" : { "address1" : "7890 N. There St.", "city" : "Phoenix", "state" : "Arizona", "zip" : "85006" "country" : "us" } }

Example document of merged one-to-many relationship with specific keys Combined document one to many

many-to-many relationship

/* Denormalized many-to-many document{"username" : "chris", "followers" : [ {"user_id" : "", "username" : "trent"}, {"user_id" : "", "username" : "eve"} ], "following" : [ {"user_id" : "", "username" : "alice"}, {"user_id" : "", "username" : "bob"} ]}

反规范化

function(newDocument) {

if(!newDocument.addresses){ throw( { forbidden : 'User document requires an addresses key!' }); } if(!newDocument.addresses.length < 1){ throw( { forbidden :'User document requires at least one address!' }); }}

Validating your data

Developing CouchDB Applications with CouchApp

安装所需要的组件

CouchApp—a set of scripts that allow complete, stand-alone CouchDB applications to be built using just HTML and JavaScript. These applications are housed in the CouchDB database, meaning that when the database is replicated, any applications stored in that database are also replicated

A Simple Task Manager

在命令行中进入 F 盘,敲 Couchapp generate couchtasks ,生成如图所示

在 _attachments 子目录中存放我们的 web 资源文件,我们可以加以修改

上传到服务器 couchapp push . http://127.0.0.1:5984/couchtasks

CouchApp

client-side application

Advantages : flexibility and portability

Serverside Application

using CouchDB as a traditional database back end to a serverside application developed in Python , Ruby, Django

Creating a CouchDB Database in Python

from couchdbkit.client import Serverserver = Server()server.create_db(“python_test”)Couchdbkit 的目标是为您的 Python 的应用提供调用和管理 Couchdb 的框架。网站地址: http://couchdbkit.org/

Python IDE

这个工具我也是用了一会 , 我打算统一使用jetBrains  提供的

Python IDE: pycharm下载链接http://www.jetbrains.com/pycharm/

Creating a CouchDB Database in Ruby

Couchrest 是一个 CouchDB RESTful Ruby 客户端

网址地址: https://github.com/couchrest/couchrest/wiki/couchrest-core

Ruby IDE

RubyMine 下载链接地址:

http://www.jetbrains.com/ruby/download/index.html

Django

网址 : http://www.djangoproject.com/

杂谈

我们需要在服务器上进行逻辑处理和创建网页,但现在这种需要将会大幅下降,在极端情况下,服务器可能只需提供数据库服务即可。

当然这只是假设在极端的情况下会如此。对于复杂的、需要协调大量服务的、或对浏览器处理应用程序的安全性不放心的企业应用程序,服务器软件将继续发挥不可或缺的作用。但对服务于大众消费者的主流商业应用程序而言,“客户端为重,服务器为轻”的前景似乎已无可置疑。

学习资料

•http://couchdb.apache.org/

•http://wiki.apache.org/couchdb

That is all

Thanks ,BYE-BYE!