コアアンサー
次のように、一意に保ちたいフィールドを持つドキュメントのPOST/PUTを構成します。
ビューを作成します。map 関数では、キーとして一意にするフィールドを使用します。値は何もありません。reduce 関数を使用して、各キーのカウントを取得します。(パフォーマンスのための) 最善の方法は、組み込みの_count reduce 関数を使用することです。
新しいドキュメントをデータベースにPUT/POSTした直後に、返さid
れた andrev
を取得して / yourdb /_design/yourapp/_view/viewname?group=true&key=" value-of-your-unique-field-from-step-1 を取得します。 "。
最後のGETの結果が1以外のカウント値を返す場合は、重複を挿入しただけです。すぐに / yourdb / id-from-step-2 ?rev= rev-from-step-2 を削除します。
リラックス。
大まかな例
ユーザーアカウントを保存していて、電子メールアドレスが一意であることを確認したいが、(何らかの理由で) ドキュメント ID にしたくないとします。上記のように、電子メール アドレスの一意性をすばやく確認するためのビューを作成します。それをemailと呼びましょう。おそらくこれに似たマップ機能があります...
function(doc) {
if(doc.type === 'account') {
emit(doc.email, 1);
}
}
そしてreduce関数_count
と同じように. 上記のように1を発行する場合も機能します。上記のようにドキュメントにフィールドを設定してチェックすることは単なる慣例ですが、役立つ場合もあります。保存しているのがユーザー アカウントだけの場合、おそらくそれは必要ありません。_sum
type
今、そのようにドキュメントを挿入しているとしましょう...
POST /mydb/
{
"name": "Joe",
"email": "joe@example.org"
}
そして、CouchDBは次のような応答を返します...
{
ok: true,
id: 7c5c249481f311e3ad9ae13f952f2d55,
rev: 1-442a0ec9af691a6b1690379996ccaba6
}
データベースに複数の joe@example.org があるかどうかを確認します...
GET /mydb/_design/myapp/_view/emails/?group=true&key="joe@example.org"
そして、CouchDB は次のような応答を返します...
{
rows: [
{
key: "joe@example.org",
value: 1
}
]
}
value
その返信以外の場合は1
、重複したメールを挿入した可能性があります。そのため、ドキュメントを削除し、典型的な SQL データベースの応答と同様に、Email Address must be Uniqueの行に沿ってエラーを返します。
削除は次のようになります...
DELETE /mydb/7c5c249481f311e3ad9ae13f952f2d55?rev=1-442a0ec9af691a6b1690379996ccaba6
短いディスカッション(気にする場合)
あなたが古き良き*SQLの背景から来ているなら、これは間違っていて奇妙に思えるでしょう. フリップアウトする前に、これらの点を考慮してください。一意性など、フィールドに制約があることは、schemaを意味します。CouchDB はスキーマレスです。*SQL から来るということは、考え方を変える必要があるということです。ACID とロックだけが方法ではありません。CouchDB には多くの柔軟性とパワーがあります。必要なものを得るためにそれをどのように使用するかは、ユース ケースの詳細と、従来のリレーショナル データベースの考え方の制限をどれだけうまく回避できるかによって異なります。
私が時々このように独自性を実装する理由は、それが私にとって非常に心地よく感じられるからです。CouchDB が更新の競合などを処理する方法について考えてみると、このアプローチは同じフローに従います。与えられたドキュメントを保存し、フィールドが一意かどうかを確認します。そうでない場合は、挿入したばかりのドキュメントをまだ保持している便利なハンドルで取得し、たとえば削除するなど、一意性の必要性を解決するために何かを行います。
上記の例では、ドキュメントを作成する前にメール アドレスの一意性を確認したくなるかもしれません。POST
気をつけて!!複数のことが起こっている場合、メールが存在するかどうかを確認した直後に、同じメールアドレスを持つ別のドキュメントがデータベースに挿入される可能性がありますが、! そうすると、重複したメールが残ります。POST
の前にメールアドレスのチェックも実行しても問題ありませんPOST
。たとえば、ユーザーがフォームに入力していて、電子メール フィールドの値をデータベースに ajax できる場合、これは良い考えです。メールアドレスが存在することをユーザーに事前に警告したり、送信を防止したりできます。ただし、すべての場合において、ドキュメントを作成した後に常に一意であることも確認する必要があります。その後、必要に応じて対応します。UI 側から見ると、上記の手順は、一意性制約を利用して従来の *SQL データベースから取得した結果と何ら変わりはないように見えます。POST
何か問題が発生する可能性はありますか? はい。このことを考慮。joe@example.orgがまだデータベースに存在していないとします。2 つのドキュメントがほぼ同時にデータベースに保存されます。Doc AはPOSTed
、次にDoc Bは ですが、 Doc APOSTed
の一意性を確認する前に. したがって、 Doc Aの一意性チェックを行うと、joe@example.orgがデータベースに 2 回あることがわかります。そのため、削除して問題を報告します。しかし、 Doc Aを削除する前に、 Doc Bの一意性チェックも行われ、 joe@example.orgに対して同じカウント値が取得されるとしましょう。今は両方 POST
POST
POSTs
たとえjoe@example.orgがもともとデータベースに存在しなかったとしても、拒否されます! つまり、値が一致する 2 つのドキュメントがほぼ同時にアプリに入力された場合、それらのドキュメントが互いを認識し、その値が既にデータベースにあると誤って判断する可能性があります。CouchDBには従来の RDB スタイルのロックPOSTs
がないため、これを完全に防ぐことはできません。しかし、そのわずかな価格と引き換えに、マスター間のレプリケーションやその他の優れた機能を大量に手に入れることができます。買います!これが実装にとって大きな問題である場合は、何らかの再試行メカニズムを実装するなどして対処することができます。
最後に、CouchDB は本当にデータベースの宝石ですが、これだけを受け入れて防弾アプローチであると期待しないでください。実際には、特定のアプリケーションの詳細に大きく依存します。