ドキュメントの検索:クエリを使って検索する
Cosmos DBは、デフォルトでドキュメント内の全てのフィールドにインデックスを付与します。そのため、ID以外のフィールドであっても高速に検索することが可能となっています。
ID以外の項目の場合、クエリを使うことで検索条件として利用することができます。以下のGetDocumentByQueryAsyncメソッドでは、検索条件(predicate)を引数として受け取るようにしています。
public static T GetDocumentByQuery(Expression<Func<T, bool>> predicate)
{
return client.CreateDocumentQuery<T>(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId))
.Where(predicate)
.AsEnumerable()
.FirstOrDefault();
}
メソッドの呼び出し側で検索条件を組み立てます。例えば、作成者で検索したい場合はリスト7の書き方です。
static TodoDocument SearchDocumentByQuery()
{
// 作成者を指定したドキュメントの検索
var document = DocumentRepository<TodoDocument>.GetDocumentByQuery(
(doc) => doc.Auther.Equals("yamada")
);
// ドキュメントを整形してコンソールに出力する
Console.WriteLine(JsonConvert.SerializeObject(document, Formatting.Indented));
return document;
}
MainメソッドからGetDocumentByQueryAsyncメソッドを呼び出すように修正し、Program.csを実行します(なお、ドキュメントの作成とIDによる検索は一時的にコメントアウトしています)。
static void Main(string[] args)
{
// データベース-コレクションの作成(存在しない場合)
DocumentRepository<TodoDocument>.Initialize();
// ドキュメントの作成
// var SessionId = CreateDocumentAsync().Result;
// IDによるドキュメントの検索
// SearchDocumentById(SessionId).Wait();
// 検索条件によるドキュメントの検索
SearchDocumentByQuery();
// キー入力があるまでコンソールを表示する
Console.ReadKey();
}
すると、作成者(auther)が「yamada」のドキュメントだけが取得できるようになりました。このクエリを使った検索結果は、以下のSQLで検索をした場合と等価になります。
SELECT * FROM c WHERE c.auther = 'yamada';
ドキュメントの更新
続いてはドキュメントの更新を行ってみましょう。
Cosmos DBにはドキュメントのアップサートをするためのUpsertDocumentAsyncメソッドが用意されているので、それを使います。アップサートは、ドキュメントが既にCosmos DBに存在すれば更新(アップデート)を、存在しなければ追加(インサート)を行うAPIです。
ドキュメント追加用のAPIとしては、前回紹介したCreateDocumentAsyncメソッドがありますが、既に存在するドキュメントをもう一度追加しようとするとエラーとなります。UpsertDocumentAsyncメソッドはエラーとならないため、利便性の面で優れています。ただし、本来更新するべきではないドキュメントを誤って更新してしまうといったケースも発生しかねないため、用途に応じてUpsertDocumentAsyncとCreateDocumentAsyncを使い分けることが大切です。
public static async Task UpsertDocumentAsync(T document)
{
await client.UpsertDocumentAsync(
UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId),
document);
}
Program.csにUpdateDocumentメソッドを追加し、Mainメソッドから呼び出すように修正します。
static async Task<TodoDocument> UpdateDocument(TodoDocument document)
{
document.IsCompleted = true;
document.CompleteDate = DateTime.Now;
await DocumentRepository<TodoDocument>.UpsertDocumentAsync(document);
return document;
}
static void Main(string[] args)
{
// データベース-コレクションの作成(存在しない場合)
DocumentRepository<TodoDocument>.Initialize();
// 検索条件によるドキュメントの検索
var document = SearchDocumentByQuery();
// ドキュメントの更新
UpdateDocument(document).Wait();
// キー入力があるまでコンソールを表示する
Console.ReadKey();
}
Program.csを実行後、Emulatorを更新して該当のドキュメントのプロパティ(isCompletedとcompleteDate)が更新されていれば成功です。
