couchdbkitでCouchDBにファイルを登録する

Python + couchdbkitでCouchDBに画像ファイルを登録してみたいと思います。

ドキュメントが見つけられず苦労しました。。。



参考ソース



ドキュメントが見つけられなかったので、couchdbkitのテストコードを参考にしました。
http://github.com/benoitc/couchdbkit/blob/master/tests/client_test.py

290行目付近の、testInlineAttachmentsを参考にしています。




_attachments



CouchDBで_idや、_revというキーが特別な意味を持っているのと同じく、
_attachmentsも特別な意味を持つキーワードでした。

このキー配下にファイルのデータが格納されます。

_attachments/[ファイル名]/data
ここに登録したいファイルのバイナリを指定してやります。




サンプルコード



サンプルとして、CouchDBのロゴを登録してみました。
eatというデータベースのidが0000のデータに対し、logo.pngというファイル名で登録しています。



# -*- coding:utf-8 -*-

from couchdbkit import *

#接続するCouchDBのURL
uri = "http://192.168.1.245:5984"

#接続
server = Server(uri)

#eatというデータベースを作成
db = server.get_or_create_db('eat')


f = open("logo.png", "rb")

doc = {}
doc['_id'] = '0000'
doc['description'] = u"画像登録サンプル"

#ファイルを読み込んで連想配列に設定
attach = {}
attach['data'] = f.read()


#ファイル名をキーに、データを設定
attachments = {}
attachments['logo.png'] = attach
doc['_attachments'] = attachments

""" 要するに、以下の形式のデータを作成する
doc = {'_id': "0000",
            "description": u"画像登録サンプル",
            "_attachments": {
                "logo.png": {
                    "data": f.read()
                }
            }
        }
"""

f.close()

db.save_doc(doc)





プログラム実行後、Futonの様子はこんな感じになります。

01_001_20100212182701.png




ファイルの参照



getでアクセスしてやると、画像ファイルが表示されました。

形式は、
http://[サーバー名]:[ポート番号]/[データベース名]/[ドキュメントのID]/[ファイル名]

上記のサンプルプログラムだと
http://192.168.1.245:5984/eat/0000/logo.png
こうなります。

01_002_20100212182701.png



地味に苦労しました。。。






couchdbkitでデータベース接続時エラーが発生する

CouchDBを使って、プログラムを作成しようとしてます。
久しぶりにCouchDBを使うので、まずはデータベース作成のサンプルを書いて
思い出そうかと。


# -*- coding:utf-8 -*-

from couchdbkit import *

#接続するCouchDBのURL
uri = "http://192.168.1.245:5984/"

#接続
server = Server(uri)

#eatというデータベースを作成
db = server.get_or_create_db('eat')





CouchDBに接続して、データベースを作成するだけの簡単なサンプルですが・・・



C:\>python couch_sample.py
Traceback (most recent call last):
File "couch_sample.py", line 9, in <module>
    db = server.get_or_create_db('eat')
File "c:\python25\lib\site-packages\couchdbkit-0.4.2-py2.5.egg\couchdbkit\clie
nt.py", line 129, in get_or_create_db
    server=self)
File "c:\python25\lib\site-packages\couchdbkit-0.4.2-py2.5.egg\couchdbkit\clie
nt.py", line 247, in __init__
    server.res.head('/%s/' % url_quote(dbname, safe=":"))
File "build\bdist.win32\egg\restkit\rest.py", line 126, in head
File "c:\python25\lib\site-packages\couchdbkit-0.4.2-py2.5.egg\couchdbkit\reso
urce.py", line 153, in request
    payload=body, headers=headers, **params)
File "build\bdist.win32\egg\restkit\rest.py", line 225, in request
restkit.errors.RequestFailed: {'msg': '', 'status': 500, 'response': <couchdbkit
.resource.CouchDBResponse object at 0x00F1D3F0>}




前は、このコードで通ったと思うのですが・・・


couchdbkitのソースを見てみると


def __init__(self, uri='http://127.0.0.1:5984',
        uuid_batch_count=DEFAULT_UUID_BATCH_COUNT, resource_instance=None):



どうやら、最後にスラッシュを含めちゃダメみたい。



# -*- coding:utf-8 -*-

from couchdbkit import *

#接続するCouchDBのURL
uri = "http://192.168.1.245:5984"

#接続
server = Server(uri)

#eatというデータベースを作成
db = server.get_or_create_db('eat')





このコードでちゃんとデータベースが作成できました。
仕様変わったのかな?





CouchDBのデータベース名一覧をJSONPを使用して取得する(jQuery使用)

JSONPを使用して、CouchDBに作成しているデータベース名の一覧を
取得することができました。

CouchDBのデータベース名一覧をJSONPを使用して取得する

しかし、ちょっとめんどくさい。

jQueryでJSONPを実行したほうがお手軽そうです。



CouchDBのデータベース名取得



jQueryでJSONP
こちらを参考にさせていただきました。


<html lang="ja">
<head>
    <meta http-equiv="content-script-type" content="text/javascript">
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>jQuery + JSONP</title>
    <script type="text/javascript" src="script/jquery-1.3.2.js"></script>
    <script type="text/javascript">
    
    //画面構築完了後
    $(function() {
        
        //ボタンのクリックイベントで
        $("#btn_1").click(function(){
            
            //CouchDBサーバーからデータベースの一覧を取得する
            $.getJSON("http://192.168.1.251:5984/_all_dbs?callback=?", function(data){
                var rows = "";
                
                //テーブルとして表示するため、htmlを構築
                for (i = 0; i < data.length; i++) {
                    rows += "<tr><td>";
                    rows += data[i];
                    rows += "</td></tr>";
                }
                
                //テーブルに作成したhtmlを追加する
                $("#tbl").append(rows);
            });
        });
        
    });

    </script>
</head>
<body>
    <input id="btn_1" type="button" value="データ取得" />
    <table id="tbl" border="1">
        <tbody>
            <tr>
                <th>データベース</th>
            </tr>
        </tbody>
    </table>
</body>
</html>



callback=?という記載を行うことで、引数の関数がコールバック関数として
呼び出されるようです。

最初に表示した画面
02_01_20091127000525.png

データ取得ボタンを押すと、ちゃんとデータベース名の一覧が取得できました。
02_02_20091127000525.png






CouchDBのデータベース名一覧をJSONPを使用して取得する

CouchDBから取得できる値はJSON形式なので、Javascriptとの
親和性が高いです。

CouchDBが稼動しているサーバーでWebアプリケーションを作成する場合は
問題ないのですが、WebサーバーとCouchDBサーバーを分けたい場合には、
クロスドメインとなるため、JavaScriptでデータを取得するのが難しくなります。

そんなときはJSONPです。



JSONPでデータベースの一覧を取得する



http://[CouchDBサーバーIP]:5984/_all_dbs
このアドレスにアクセスすると、


["data_base_1","data_base_2"]



こんな感じで、データベース名の一覧がJSON形式で表示されると思います。


下記のように、callbackというパラメーターをつけると
http://[CouchDBサーバーIP]:5984/_all_dbs?callback=func_name


func_name(["data_base_1","data_base_2"]);



CouchDBサーバーから、JSONPに使える文字列が返却されます。
この機能を使用して、JSONPによりデータベース名の一覧が
取得できます。




データベース名の一覧を表示するサンプル



JSONPを使ってJavaScriptだけでマッシュアップ
ここを参考にさせていただきました。

サンプルアプリケーションは以下のとおり。


<html lang="ja">
<head>
<meta http-equiv="content-script-type" content="text/javascript">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>JSONP</title>
</head>
<body>
<script type="text/javascript">
<!--
//データベース名を取得する
function getDBs() {
var url = "http://192.168.1.251:5984/_all_dbs?callback=showDBList";
callJSONP(url);
}

//JSONPを実行する関数
function callJSONP(url) {
var target = document.createElement('script');
target.charset = 'utf-8';
target.src = url;
document.body.appendChild(target);
}

//JSONPの結果として実行される関数
function showDBList( doc ) {
    var target = document.getElementById('dbs');
    for (i = 0; i < doc.length; i++) {
        target.innerHTML += doc[i] + '<br>';
    }
}
-->
</script>
<input type="button" value="データ取得" onclick="getDBs()" >
<div id="dbs" />
</body>
</html>



画面を表示したときはボタンだけ。
01_01_20091127000256.png

ボタンを押すと、データベースの一覧が表示できました。
01_02_20091127000256.png


これで、JavaScriptだけでアプリケーションを作成するめどがたちました。





CouchDBにPerlからCouchDB-Clientを使用して接続する

以前、PythonからCouchDBへの接続を試しました。
Pythonからcouchdbkitを使用してCouchDBに接続する

Perlからの接続も試してみようと思います。



CouchDB-Clientのインストール



CouchDB-ClientというモジュールがCPANにありましたので、これを使わせてもらうことにします。
http://search.cpan.org/dist/CouchDB-Client/

インストールは、以下のコマンドで実行しました。

# perl -MCPAN -e shell
cpan> install CouchDB::Client



これでインストールは完了です。




データベースへの接続



データベースへの接続と、登録されているデータベースの一覧を取得するサンプルです。
・・・といっても、サイトに掲載されているサンプルそのままですが。


#!/usr/bin/env perl

use strict;
use warnings;

use CouchDB::Client;

#データベースに接続
my $c = CouchDB::Client->new(uri => 'http://192.168.1.249:5984/');

#コネクションが作成できるかテスト
$c->testConnection or die "The server cannot be reached";

#バージョンの表示
print "==========================\n";
print "Running version " . $c->serverInfo->{version} . "\n";
print "==========================\n";

#データベースの作成
my $db = $c->newDB('my-test-db')->create;
my $db = $c->newDB('my-test2-db')->create;

# データベース名の一覧を取得する
my $db_list = $c->listDBNames;

foreach my $db_name (@$db_list) {
    print $db_name, "\n";
}

print "==========================\n";

#データベース情報の詳細を取得する
$db_list = $c->listDBs;

foreach my $db_name (@$db_list) {
    print $db_name->{"name"}, "\n";
}

print "==========================\n";





実行結果は以下のようになると思います。

# perl test.pl
==========================
Running version 0.10.0
==========================
my-test-db
my-test2-db
==========================
my-test-db/
my-test2-db/
==========================




ちなみに、このプログラムをもう一度実行すると

Connection error: 412 Precondition Failed at /usr/local/share/perl/5.10.0/CouchDB/Client/DB.pm line 50
        CouchDB::Client::DB::create('CouchDB::Client::DB=HASH(0x89254b0)') called at test.pl line 21


同じ名前のデータベースを作成しようとしたため、エラーになります。

これを回避するには、

#データベースの作成
if ($c->dbExists('my-test-db')) {
    print "既にmy-test-dbは存在します。\n";
} else {
    my $db = $c->newDB('my-test-db')->create;
}


dbExistsで、データベースが存在するか確認してやります。




ドキュメントの登録



ドキュメントの新規登録と、更新を行うサンプルです。


#!/usr/bin/env perl

use strict;
use warnings;

use CouchDB::Client;
use Data::Dumper;

#データベースサーバーと
my $c = CouchDB::Client->new(uri => 'http://192.168.1.249:5984/');

#データベースを指定
my $db = $c->newDB('my-test-db');

#新規ドキュメントの追加
#_id, _rev, 登録するドキュメントの内容を指定する
$db->newDoc('id_value', undef, { 'hoge' => 'piyo' })->create;

#作成したドキュメントを検索する
my $doc = $db->newDoc('id_value', undef, undef)->retrieve;
#検索結果を表示
print $doc->data->{'hoge'} . "\n";



#ドキュメントを更新する
#指定したドキュメントが存在するか確認
if ($db->docExists('id_value')) {
    
    #ドキュメントを取得する
    $doc = $db->newDoc('id_value', undef, undef)->retrieve;
    #内容を変更する
    $doc->data->{'hoge'} = "日本語もOK";
    
    #更新実行
    $doc->update;
} else {
    print "指定されたドキュメントは存在しません\n";
}


#ドキュメントが更新されたか確認
$doc = $db->newDoc('id_value', undef, undef)->retrieve;
#内容を変更する
print $doc->data->{'hoge'} . "\n";




実行してみると

# perl test.pl
piyo
日本語もOK



ちゃんと更新されています。





プロフィール

Author:symfo
blog形式だと探しにくいので、まとめサイト作成中です。
Symfoware まとめ

PR




検索フォーム

月別アーカイブ