Azureの小ネタ (改)

~Azureネタを中心に、色々とその他の技術的なことなどを~

CreateDocumentQueryAsync メソッドがない

DocumentDBネタが続きます。

クエリを書いていると、Document自身のCRUD操作は非同期になっているのに、クエリは同期メソッドしか用意されていません。

ということで調べていたらIssueが、以下にあがってました。

github.com

現状まだOpenですね。

        static async Task Test(DocumentClient client)
        {
            var query = client
                .CreateDocumentQuery<TestDoc>(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId))
                .Where(doc => doc.Key1 == "hoge").AsDocumentQuery();

            var list = new List<TestDoc>();
            while (query.HasMoreResults)
            {
                list.AddRange(await query.ExecuteNextAsync<TestDoc>());
            }
        }

中の人が言うには、ExecuteNextAsync をぐるぐるしろってことで、うえのようなコードになりますが、ちょいとださい。フレームワーク側で吸収してほしいなと思う感じです。Open中なので、しばしウォッチしていこうと思います。

DocumentDBのクエリ制限的なもの

Document DBのクエリ制限は、以下の書かれてます。

azure.microsoft.com

翻訳は以下。

https://blogs.technet.microsoft.com/jpitpro/2015/10/05/azure-documentdb/

  • ANDは20個まで
  • ORは10個まで
  • JOINは5個まで
  • UDFは2個まで
  • クエリページ毎に取得できるアイテムが無制限になった

まあ、通常使うキモはAND、OR、JOINの数でしょうか。JOINの数が5までってことは、6階層以上の深さをもつスキーマにクエリかけられないことを意味してる気がします。

あと地味にひっかかったが、JOINした要素に対してORDER BYがサポートされていないことでした。

{
  "id": "hoge",
  "items": [
    {
      "no": 3,
      "name": "hoge"
    },
    {
      "no": 2,
      "name": "fuga"
    },
    {
      "no": 1,
      "name": "baka"
    }
  ]
}

こんなデータがあったとき、

SELECT item.name FROM c 
JOIN item in c.items
WHERE c.id = "hoge"
ORDER BY item.no

Noでソートできません。 Order-by over correlated collections is not supported というエラーで怒られます。stackoverflow でもちらほら似た質問が散見されますからみな同じところで引っかかるんでしょうね。

DocumentDB の 添付ファイル

添付ファイルを試した時の備忘メモ。

Document作成して、添付作成して、ダウンロードする。

    var document = (await client.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), testdoc)).Resource;
    var pdf = @"C:\temp\microsoft-documentdb-sql-query-cheat-sheet-v4.pdf";

     using (var attachmentStream = File.OpenRead(pdf))
    {
         var attachment = (await client.CreateAttachmentAsync(document.SelfLink, attachmentStream,
            new MediaOptions()
            {
                ContentType = "application/pdf",
            })).Resource;

         attachment = (await client.ReadAttachmentAsync(attachment.SelfLink)).Resource;
         var media = await client.ReadMediaAsync(attachment.MediaLink);
         using (var fileStream = File.OpenWrite(@"c:\temp\download.pdf"))
         {
            media.Media.CopyTo(fileStream);
         }
    }