アマゾンAPIを活用した蔵書管理システム(3)
November 18, 2008 – 5:36 pm前回までのエントリで、アマゾンAPIを利用して書籍データを取得する仕組みを整えることができた。いよいよ、アマゾンから取得した書籍データを我がサーバ上にデータベースとして取り込む方法について移る。データベース化にあたっては、以前のエントリ「MySQLを学習(1)」において学んだリレーショナルデータベースの利点を実際に体験することになる。
データベースの設計と構築: 私のようにDBMSの初心者にとって本格的なデータベースをいちから設計するというのは骨の折れる仕事だ。そこで、Web上で紹介されている蔵書データベースにどのようなものがあるか調べることから始めた。そこで見つけたのが、「蔵書インデキシングプロジェクト活動進捗(4)」に述べられている労作。なるほど、データベースの正規化というのはこのように行うのかと感心。ということで、ここで示されているデータベース構造を借用させていただいて、蔵書データベースとすることにした。(若干、我がほうに都合のよいように変更した部分もあるが、基本的な構造はquneさんのブログの記述を活用させていただいた。感謝)
DBテーブル作成用のSQL文は以下:
BookDB.sql:
DROP TABLE IF EXISTS book_author;
DROP TABLE IF EXISTS book;
DROP TABLE IF EXISTS publisher;
DROP TABLE IF EXISTS binding;
DROP TABLE IF EXISTS role;
DROP TABLE IF EXISTS currency;
DROP TABLE IF EXISTS author;
CREATE TABLE publisher (
id INTEGER(8) PRIMARY KEY AUTO_INCREMENT,
publisher VARCHAR(256) NOT NULL
);
CREATE TABLE binding (
id INTEGER(8) PRIMARY KEY AUTO_INCREMENT,
binding VARCHAR(64) NOT NULL
);
CREATE TABLE role (
id INTEGER(8) PRIMARY KEY AUTO_INCREMENT,
role VARCHAR(32) NOT NULL
);
CREATE TABLE currency (
id INTEGER(8) PRIMARY KEY AUTO_INCREMENT,
currency_cd CHAR(3) NOT NULL
);
CREATE TABLE author (
id INTEGER(8) PRIMARY KEY AUTO_INCREMENT,
author VARCHAR(64) NOT NULL
);
CREATE TABLE book (
id INTEGER(8) PRIMARY KEY AUTO_INCREMENT,
isbn CHAR(10),
asin CHAR(10),
ean CHAR(13),
title VARCHAR(256) NOT NULL,
image_url VARCHAR(128),
pubdate DATE,
price DECIMAL(10,2),
pages INTEGER(6),
publisher_id INTEGER(8),
binding_id INTEGER(8),
currency_id INTEGER(8)
);
ALTER TABLE book ADD FOREIGN KEY (publisher_id)
REFERENCES publisher (id);
ALTER TABLE book ADD FOREIGN KEY (binding_id)
REFERENCES binding (id);
ALTER TABLE book ADD FOREIGN KEY (currency_id)
REFERENCES currency (id);
CREATE TABLE book_author (
id INTEGER(8) PRIMARY KEY AUTO_INCREMENT,
book_id INTEGER(8) NOT NULL,
author_id INTEGER(8) NOT NULL,
role_id INTEGER(8)
);
ALTER TABLE book_author ADD FOREIGN KEY (book_id)
REFERENCES book (id);
ALTER TABLE book_author ADD FOREIGN KEY (author_id)
REFERENCES author (id);
ALTER TABLE book_author ADD FOREIGN KEY (role_id)
REFERENCES role (id)
データベース作成の手続き: ここで示したSQL文に基づきデータベース作成の手続きを示すことにしよう。なお、データベース作成手順については、既に我がブログの以前のエントリー「MySQLを学習(2):DataBaseとTableの作成」において記述しており、これと重複する部分があることをお断りしておく。
まず、「蔵書管理システム」用の空のデータベースSampleDBを作成する:
# mysql -u username -p
Enter password: password
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9994
Server version: 5.0.45 Source distribution
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> create database sampleDB;
Query OK, 1 row affected (0.00 sec)
このDB上に、既に述べたBookDB.sql で定義した複数のテーブルを一括して作成する:
# mysql -u username -p SampleDB < BookDB.sql;
Enter password: password
これで、データベースSampleDBの枠組みが出来上がったはずだ。実際に、テーブルが問題なく作成されていることを確かめてみよう;
# mysql -u username -p SampleDB
Enter password: password
mysql> show tables;
+--------------------+
| Tables_in_SampleDB |
+--------------------+
| author |
| binding |
| book |
| book_author |
| currency |
| publisher |
| role |
+--------------------+
7 rows in set (0.00 sec)
mysql> describe book;
+--------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+----------------+
| id | int(8) | NO | PRI | NULL | auto_increment |
| isbn | char(10) | YES | | NULL | |
| asin | char(10) | YES | | NULL | |
| ean | char(13) | YES | | NULL | |
| title | varchar(256) | NO | | | |
| image_url | varchar(128) | YES | | NULL | |
| pubdate | date | YES | | NULL | |
| price | decimal(10,2) | YES | | NULL | |
| pages | int(6) | YES | | NULL | |
| publisher_id | int(8) | YES | MUL | NULL | |
| binding_id | int(8) | YES | MUL | NULL | |
| currency_id | int(8) | YES | MUL | NULL | |
+--------------+---------------+------+-----+---------+----------------+
12 rows in set (0.00 sec)
mysql> describe author;
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| id | int(8) | NO | PRI | NULL | auto_increment |
| author | varchar(64) | NO | | | |
+--------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> describe book_author;
+-----------+--------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------+------+-----+---------+----------------+
| id | int(8) | NO | PRI | NULL | auto_increment |
| book_id | int(8) | NO | MUL | | |
| author_id | int(8) | NO | MUL | | |
| role_id | int(8) | YES | MUL | NULL | |
+-----------+--------+------+-----+---------+----------------+
mysql> quit;
Bye
書籍データのデータベース上への反映: データベースの枠組みが完成したところで、前回のエントリーで紹介した方式で取得する書籍データを、このデータベース上に反映させなければならない。前回説明したように、取得データは、個々の書籍について2種類のデータオブジェクト(DTO形式:Book、Author_array)で得られる。次の作業は、これらDTO形式のデータを上記したSQLデータベースSampleDBに取り込むための仕組みを作成することになる。
SampleDBへのデータの取り込みを行うため、Daoオブジェクト(BookDao)を作成し、このなかに、新規の書籍データを取り込むためのメソッドinsertBook()を作成した。BookDaoのphpソースは最後に掲げることにし、実際に、これを用いて書籍データをデータベースに登録する手続きをサンプルとして以下にしめしてみよう:
サンプルでは、前回のエントリーで取り扱った本「利己的な遺伝子」をデータベース上に取り込むことにする。そのためのSample.phpを作成する:
Sample.php
<?php
require_once("SetBookByBookID.php");
require_once("BookDao.php");
$BOOK_ID = '4314005564';
$BookCode = 'ISBN';
$rtn = SetBookByBookID($BOOK_ID, $BookCode);
$book = $rtn[0];
$author_array = $rtn[1];
$bookdao = new BookDao();
$bookdao->insertBook($book, $author_array);
$book = NULL;
$author_array = NULL;
$bookdao = NULL;
?>
このphpスクリプトでは、まず前回作成したSetBookByBookID()を用いて書籍データを二つのデータオブジェクト$bookと$author_arrayで取得する。このデータを新たに作成したクラスBookDaoのメソッドinsertBook()の引数とし、これによりSampleDB上に反映している。
この方法で9冊の書籍を、逐次、データベースSampleDB上に取り込み、SampleDB上にデータが正しくとりこまれていることを確認してみた。
mysql> select id, title from book;
+----+-----------------------------------------------------------------------------------------------+
| id | title |
+----+-----------------------------------------------------------------------------------------------+
| 1 | 利己的な遺伝子 (科学選書) |
| 2 | 盲目の時計職人 |
| 3 | はじめての年金・医療保険―保険の基本は社会保険から (集英社新書) |
| 4 | 科学者の新しい役割 (双書科学/技術のゆくえ) |
| 5 | 第二種基礎研究 |
| 6 | 免疫の意味論 |
| 7 | 公共のための科学技術 |
| 8 | 生態学的視覚論―ヒトの知覚世界を探る |
| 9 | 「病気」の誕生―近代医療の起源 (平凡社選書) |
+----+-----------------------------------------------------------------------------------------------+
9 rows in set (0.00 sec)
mysql> select id, author from author;
+----+-----------------------------------+
| id | author |
+----+-----------------------------------+
| 1 | リチャード・ドーキンス |
| 2 | 日高 敏隆 |
| 3 | 岸 由二 |
| 4 | 羽田 節子 |
| 5 | 垂水 雄二 |
| 6 | 児玉 美穂 |
| 7 | 吉川 弘之 |
| 8 | 内藤 耕 |
| 9 | 多田 富雄 |
| 10 | 小林 伝司 |
| 11 | J.J.ギブソン |
| 12 | 古崎 敬 |
| 13 | 児玉 善仁 |
+----+-----------------------------------+
13 rows in set (0.00 sec)
mysql> select id, role from role;
+----+--------+
| id | role |
+----+--------+
| 1 | |
| 2 | 翻訳 |
| 3 | 編集 |
+----+--------+
3 rows in set (0.00 sec)
mysql> select * from book_author;
+----+---------+-----------+---------+
| id | book_id | author_id | role_id |
+----+---------+-----------+---------+
| 1 | 1 | 1 | 1 |
| 2 | 1 | 2 | 2 |
| 3 | 1 | 3 | 2 |
| 4 | 1 | 4 | 2 |
| 5 | 1 | 5 | 2 |
| 6 | 2 | 1 | 1 |
| 7 | 2 | 2 | 2 |
| 8 | 3 | 6 | 1 |
| 9 | 4 | 7 | 1 |
| 10 | 5 | 7 | 1 |
| 11 | 5 | 8 | 1 |
| 12 | 6 | 9 | 1 |
| 13 | 7 | 10 | 3 |
| 14 | 8 | 11 | 1 |
| 15 | 8 | 12 | 1 |
| 16 | 9 | 13 | 1 |
+----+---------+-----------+---------+
16 rows in set (0.00 sec)
mysql> select id, publisher from publisher;
+----+-----------------------+
| id | publisher |
+----+-----------------------+
| 1 | 紀伊國屋書店 |
| 2 | 早川書房 |
| 3 | 集英社 |
| 4 | 岩波書店 |
| 5 | 日経BP社 |
| 6 | 青土社 |
| 7 | 玉川大学出版部 |
| 8 | サイエンス社 |
| 9 | 平凡社 |
+----+-----------------------+
9 rows in set (0.00 sec)
テーブル上に書き込まれたデータが想定した通りデータベース上にあることが確認される。なお、アマゾンの書籍データベースへのアクセスは1秒に1回の制限があることから、アマゾンからの書籍データ取り込み用関数SetBookByBookID()を使用する際に注意したい。
さて、これでデータベースへの書籍データの取り込みは行うことができた。次回は、今回作成したSampleDBからのデータのk検索など、その操作方法についてみることにしよう。
BookDao.php:
<?php
Class BookDao {
private $mysqli = null;
//Constructor
function __constructor() {
$this->connect();
}
//Destructor
function __destruct() {
$this->disconnect();
}
//Connect to MySQL server
private function connect() {
if(is_null($this->mysqli)) {
$this->mysqli = new mysqli("localhost", "user_name", "password", "SampleDB");
$this->mysqli->query("SET NAMES utf8");
if(mysqli_connect_errno()) {
die("Failed to connect to MySQL server<br></br> Reason:" . mysqli_connect_error());
}
}
}
//Disconnect from MySQL server
private function disconnect() {
is_null($this->mysqli) or $this->mysqli->close();
}
// Register New Book_Data for tables
public function insertBook( $book, $author_array ) {
is_null($this->mysqli) and $this->connect();
// check book to be registered in Table Book
$sql = "SELECT id FROM book WHERE asin='". $book->getAsin() . "'";
$result = $this->mysqli->query($sql);
if ( $result->num_rows != 0 ) {
$row = $result->fetch_array(MYSQLI_ASSOC);
echo "This book is already registered! \n";
$book_id = $row["id"];
echo "book_id registered = " . $book_id . "\n" ;
}
else {
// Set publisher table and publisher_id
$sql = "SELECT id FROM publisher WHERE publisher='" . $book->getPublisher() . "'";
$result = $this->mysqli->query($sql);
if ( $result->num_rows == 0 ) {
$sql = "INSERT INTO publisher values('',
'" . $book->getPublisher() . "')";
if (!$this->mysqli->query($sql)) {
print "Failed to register(1002) " . $this->mysqli->error . "\n";
}
else {
$publisher_id = $this->mysqli->insert_id;
}
}
else {
$row = $result->fetch_array(MYSQLI_ASSOC);
$publisher_id = $row["id"];
}
// Set binding table and binding_id
$sql = "SELECT id FROM binding WHERE binding='" . $book->getBinding() . "'";
$result = $this->mysqli->query($sql);
if ( $result->num_rows==0 ) {
$sql = "INSERT INTO binding values('',
'" . $book->getBinding() . "')";
if (!$this->mysqli->query($sql)) {
print "Failed to register(1003) " . $this->mysqli->error . "\n";
}
else {
$binding_id = $this->mysqli->insert_id;
}
}
else {
$row = $result->fetch_array(MYSQLI_ASSOC);
$binding_id = $row["id"];
}
// Set currency table and currency_id
$sql = "SELECT id FROM currency WHERE currency_cd='" . $book->getCurrency_cd() ."'";
$result = $this->mysqli->query($sql);
if ( $result->num_rows == 0 ) {
$sql = "INSERT INTO currency VALUES('',
'" . $book->getCurrency_cd() . "')";
if (!$this->mysqli->query($sql)) {
print "Failed to register(1004) " . $this->mysqli->errro . "\n";
}
else {
$currency_id = $this->mysqli->insert_id;
}
}
else {
$row = $result->fetch_array(MYSQLI_ASSOC);
$currency_id = $row["id"];
}
// Set Book Table for new data
$sql = "INSERT INTO book values('',
'" . $book->getIsbn() . "',
'" . $book->getAsin() . "',
'" . $book->getEan() . "',
'" . $book->getTitle() . "',
'" . $book->getImage_url() . "',
'" . $book->getPubdate() . "',
'" . $book->getPrice() . "',
'" . $book->getPages() . "',
'" . $publisher_id . "',
'" . $binding_id . "',
'" . $currency_id . "')";
if( !$this->mysqli->query($sql) ) {
print "Failed to register(1005) " . $this->mysqli->error . "\n";
}
else {
$book_id = $this->mysqli->insert_id;
}
// Set Author Table for new data
for ( $i=0; $i<sizeof($author_array); $i++) {
$sql = "SELECT id FROM author where author='" . $author_array[$i]->getAuthor() . "'";
$result = $this->mysqli->query($sql);
if ( $result->num_rows == 0 ) {
$sql = "INSERT INTO author values('',
'" . $author_array[$i]->getAuthor() . "')";
if(!$this->mysqli->query($sql)) {
print "Failed to register(1006) " . $this->mysqli->error . "\n";
}
else {
$author_id = $this->mysqli->insert_id;
}
}
else {
$row = $result->fetch_array(MYSQLI_ASSOC);
$author_id = $row["id"];
}
$sql = "SELECT id FROM role where role='" . $author_array[$i]->getRole() . "'";
$result = $this->mysqli->query($sql);
if ( $result->num_rows == 0 ) {
$sql = "INSERT INTO role values('',
'" . $author_array[$i]->getRole() . "')";
if(!$this->mysqli->query($sql)) {
print "Failed to register(1007) " . $this->mysqli->error . "\n";
}
else {
$role_id = $this->mysqli->insert_id;
}
}
else {
$row = $result->fetch_array(MYSQLI_ASSOC);
$role_id = $row["id"];
}
$sql = "INSERT INTO book_author values('',
'" . $book_id . "','" . $author_id . "','" . $role_id . "')";
if( !$this->mysqli->query($sql) ) {
print "Failed to register(1008) " . $this->mysqli->error . "\n";
}
}
}
}
}
?>
1 Trackback(s)