groongaでレコードを削除する方法

groongaやmroongaを実際に使っていて、記事を書いてもいいよ、という人を募集しています。
すでに数名の方からご応募いただいていますが、まだまだ募集中です。
詳細は[groonga普及のための協力のお願い](http://sourceforge.jp/projects/groonga/lists/archive/dev/2013-February/001186.html)を参照してください。

# はじめに

オープンソースの[カラムストア機能付き全文検索エンジンgroonga](http://groonga.org/ja/)を公開しています。
この記事を書いたときの最新のバージョンは2013年2月28日にリリースした3.0.1です。

[前回](http://qiita.com/items/d73645af9ca8e83b3c79)は、[loadコマンド](http://groonga.org/ja/docs/reference/commands/load.html)を使って特定のカラムを更新する方法を紹介しました。また、その中で定義したテーブルにデータを登録する方法も紹介しました。
そこで、今回は逆にgroongaのテーブルからレコードを削除する方法を紹介します。データを投入していって、不要になったレコードを削除したくなったときに使えます。

groongaにはレコードを削除する方法が次の3つあります。

* 主キーやIDを指定する
* 削除したいレコードの条件を指定する
* テーブルに登録されたレコードすべてを削除する

最初に実際にレコードの削除を試すためのサンプルを示します。次に、それぞれの削除方法について簡単に紹介します。

# サンプルのスキーマとデータ

以下はサンプルとして使うテーブルのスキーマです。

```
table_remove Books
table_create Books TABLE_HASH_KEY UInt32
column_create Books title COLUMN_SCALAR ShortText
column_create Books price COLUMN_SCALAR Int32
```

Booksというテーブルを作成し、本のタイトルを格納するtitleカラムと、値段を格納するpriceカラムを定義しました。
このテーブルに、前回も紹介したloadコマンドでデータを登録します。

```
load --table Books
[
{"_key":1, "title":"Head First Groonga", "price": 3400},
{"_key":2, "title":"Head First Mroonga", "price": 2800},
{"_key":3, "title":"Groonga command manual", "price": 1000},
{"_key":4, "title":"Head First Rroonga", "price": 2000},
{"_key":5, "title":"Mroonga manual", "price": 2500}
]
```

正しく登録できたかを、次のselectコマンドで確認します。

```
select Books --output_columns _key,title,price
```

上記コマンドの ```--output_columns _key,title,price``` というのは表示するカラムを指定する引数です。
上のコマンドを実行した結果を見やすいように抜粋し、整形すると以下のようになります。
（なお、以降の実行結果も適宜抜粋・整形しており、実際の実行結果には他にも情報が出力されます。詳しくは[出力内容についてのドキュメント](http://groonga.org/ja/docs/reference/command/output_format.html)をご覧ください。）

```
[
  [
    [5],
    [["_key","UInt32"],["title","ShortText"],["price","Int32"]],
    [1,"Head First Groonga",3400],
    [2,"Head First Mroonga",2800],
    [3,"Groonga command manual",1000],
    [4,"Head First Rroonga",2000],
    [5,"Mroonga manual",2500]
  ]
]
```

実行結果を見ると、loadコマンドで登録した5つのレコードがBooksテーブルにあることがわかります。

# 主キーやIDを指定する

レコードを削除するには、[deleteコマンド](http://groonga.org/ja/docs/reference/commands/delete.html)を使用します。
deleteコマンドはテーブル名と、削除するレコードの主キーの値やIDの値、もしくは後述しますが条件式を指定できます。
今回は、次のように_keyカラムの値が2のレコードを削除してみます。

```
delete Books 2
```

正しく削除が行われると、次のように実行結果が表示されます。

```
[true]
```

もし削除できなかった場合は ```[false]``` が返ってくるので、テーブル内のレコードの内容と実行したdeleteコマンドを確認してください。
さて、正しく削除されたかどうかをselectコマンドで確認してみましょう。先ほどと同じように、Booksテーブルの中身を確認してみます。

```
select Books --output_columns _key,title,price
```

正しく削除されている場合、次のような結果が返ってきます。

```
[
  [
    [4],
    [["_key","UInt32"],["title","ShortText"],["price","Int32"]],
    [1,"Head First Groonga",3400],
    [3,"Groonga command manual",1000],
    [4,"Head First Rroonga",2000],
    [5,"Mroonga manual",2500]
  ]
]
```

実行結果を見ると、レコード数が5つから4つに減り、主キーが2のレコードが削除されていることがわかります。

もし、主キーの値でなく、IDの値を指定したい場合は、まず次のようなselectコマンドでIDの値を確認します。

```
select Books --output_columns _id,_key,title,price
```

先ほど実行したselectコマンドとの違いは、 ```--output_columns``` 引数に対して ```_id``` という文字列を指定しているところです。これはレコードのIDを表示するためです。このselectコマンドを実行すると、次のように結果が返ってきます。

```
[
  [
    [4],
    [["_id","UInt32"],["_key","UInt32"],["title","ShortText"],["price","Int32"]],
    [1,1,"Head First Groonga",3400],
    [3,3,"Groonga command manual",1000],
    [4,4,"Head First Rroonga",2000],
    [5,5,"Mroonga manual",2500]
  ]
]
```

上記の実行結果のうち、各レコードの最初の値がそのレコードのIDです。
このうち、IDが5のレコードを消すには、次のように ```--id``` 引数を指定してdeleteコマンドを実行してください。

```
delete Books --id 5
```

正しく削除できていると、次のように実行結果が表示されます。

```
[true]
```

先ほどと同じselectコマンドを実行してみましょう。

```
select Books --output_columns _id,_key,title,price
```

正しく削除できている場合は、実行すると次のような実行結果が返ってきます。

```
[
  [
    [3],
    [["_id","UInt32"],["_key","UInt32"],["title","ShortText"],["price","Int32"]],
    [1,1,"Head First Groonga",3400],
    [3,3,"Groonga command manual",1000],
    [4,4,"Head First Rroonga",2000]
  ]
]
```

IDが5のレコードが削除されているのがわかります。

# 削除したいレコードの条件を指定する

先ほどの方法だと1つずつしかレコードを削除できません。例えば、"Groonga"という文字列がタイトルに含まれているレコードを先ほどの方法で削除しようとすると、titleカラムの値を見ながら1つずつ主キーの値を指定してdeleteコマンドを実行しなくてはなりません。
このように、削除したいレコードの条件が決まっているときには、deleteコマンドにfilter引数を指定することで条件を満たしたレコードを削除することができます。
条件はgroongaの[スクリプト構文](http://groonga.org/ja/docs/reference/grn_expr/script_syntax.html)という記法に従って書きます。これは[selectコマンド](http://groonga.org/ja/docs/reference/commands/select.html)で全文検索するときにも使える記法です。そのため、deleteコマンドを使って全文検索し、ヒットしたレコードを削除することができます。スクリプト構文の詳しい書き方についてはリンク先をご覧下さい。

ここでは、「titleカラムに"Groonga"という単語が含まれている」という条件に当てはまったレコードを削除してみます。次のようにdeleteコマンドを実行してください。 ```'title @ "Groonga"'``` の部分が上記の条件を示しています。

```
delete Books --filter 'title @ "Groonga"'
```

これも、削除が成功すると次のように表示されます。

```
[true]
```

レコードが削除されているか、selectコマンドで確かめてみましょう。
なお、先ほど実行したselectコマンドの結果を見ると、"Groonga"という文字列が含まれるタイトルは主キーの値が1と3のレコードがもっていました。

```
select Books --output_columns _key,title,price
```

正しく削除されているなら次のような実行結果になります。

```
[
  [
    [1],
    [["_key","UInt32"],["title","ShortText"],["price","Int32"]],
    [4,"Head First Rroonga",2000]
  ]
]
```

selectコマンドの実行結果を見ると、確かに主キーの値が1と3のレコードが削除され、レコードの数が1つになっていることがわかります。

# テーブルに登録されたレコードすべてを削除する

条件を指定せず、テーブルに登録されたレコードを全て削除するには、[truncateコマンド](http://groonga.org/ja/docs/reference/commands/truncate.html)を利用します。truncateコマンドはテーブル名を指定すると、そのテーブル内にあるレコードをすべて削除します。
それでは、残っているレコードを削除してみましょう。残っているのは主キーの値が4のレコードでした。次のコマンドを実行してください。

```
truncate Books
```

truncateコマンドには、レコードを指定するための値を何も指定していないのがわかります。
上記のコマンドが成功すると次のような実行結果になります。

```
[true]
```

次のselectコマンドで、Booksテーブルにレコードがないことを確認しましょう。

```
select Books --output_columns _key,title,price
```

```
[
  [
    [0],
    [["_key","UInt32"],["title","ShortText"],["price","Int32"]]
  ]
]
```

レコードの件数が0になっており、何もレコードが出力されていないことから、Booksテーブルからレコードがすべて削除されたことがわかります。

なお、deleteコマンドとtruncateコマンドどちらを使った場合でも、いちど削除したレコードを戻すことはできません。もし消してもいいか不安がある場合はデータベースをバックアップしておくと安心です。（バックアップには[dumpコマンド](http://groonga.org/ja/docs/reference/commands/dump.html)が利用できます。）

# まとめ

今回はgroongaで不要になったレコードを削除するための方法について紹介しました。

groongaに興味を持ったなら、まずは[インストール](http://groonga.org/ja/docs/install.html)して試してみてください。

groongaの基本的な動作を知るための[チュートリアル](http://groonga.org/ja/docs/tutorial.html)もあります。