2012-08-09 42 views
2

我正在使用azure表存儲來存儲博文。每篇博文都可以有不同的標籤。 所以我會有三個不同的表格。對azure表的動態查詢

  • 一個將存儲博客文章。
  • 一個用於存儲標籤
  • 一個將存儲在標籤和崗位

所以我的問題是如下的關係,是有可能創造動態搜索queuries?因爲直到運行時我才知道要搜索多少個標籤。 據我所知,你只能使用LINQ查詢天藍色的表格。或者我可以輸入一個字符串查詢,我可以動態更改?

UPDATE

下面是一些例子數據是在博客表

PartitionKey,RowKey,Timestamp,Content,FromUser,Tags 
user1, 1, 2012-08-08 13:57:23, "Hello World", "root", "yellow,red" 

blogTag表

PartitionKey,RowKey,Timestamp,TagId,TagName 
"red", "red", 2012-08-08 11:40:29, 1, red 
"yellow", "yellow", 2012-08-08 11:40:29, 2, yellow 

關係表

PartitionKey,RowKey,Timestamp,DataId,TagId 
1, 1, 2012-08-08 11:40:29, 1, 1 
2, 1, 2012-08-08 13:57:23, 1, 2 

這些表格的一個用法示例是,例如,當我想用​​特定標籤獲取所有博客文章時。

  • 我不得不從blogTag表
  • 有後,我需要在關係表來搜索數據ID
  • 最後,我需要尋找博客表博客文章與數據ID查詢標籤識別

我使用LINQ進行查詢,它看起來像下面

CloudTableQuery<DataTag> tagIds = (from e in ctx2.CreateQuery<DataTag>("datatags") 
            where e.PartitionKey == tags 
            select e).AsTableServiceQuery<DataTag>(); 

我想嘎urav Mantri使用過濾器的建議,它的工作原理。但我擔心這種效率會如何。而關於15個離散比較的限制只允許。

+0

您不限於LINQ。最後它是ATS的REST呼叫。但是你可以使用LINQ來創建動態查詢(E.G。State ='WA'或State ='CA')。請提供您在LINQ和ATS設計中無法完成的查詢的示例。我認爲REST API僅限於40個過濾器。 40可能是錯誤的數字,但有一個限制。 – Paparazzi 2012-08-09 14:59:17

+0

多個條件可以是單個過濾器的多個查詢(並行),然後在.NET中執行交集或聯合。爲您的查詢設計PartitionKey和RowKey。 – Paparazzi 2012-08-09 15:08:54

+0

@Blam我更新問題與我用來搜索標籤,以及一些示例表的查詢。我發現這個限制是15或14,因此對breischl的回答 – starcorn 2012-08-09 15:24:18

回答

1

我也面臨完全相同的問題。我沒有找到一個解決方案,我在下面粘貼:

public static IEnumerable<T> Get(CloudStorageAccount storageAccount, string tableName, string filter) 
    { 
     string tableEndpoint = storageAccount.TableEndpoint.AbsoluteUri; 
     var tableServiceContext = new TableServiceContext(tableEndpoint, storageAccount.Credentials); 
     string query = string.Format("{0}{1}()?filter={2}", tableEndpoint, tableName, filter); 
     var queryResponse = tableServiceContext.Execute<T>(new Uri(query)) as QueryOperationResponse<T>; 
     return queryResponse.ToList(); 
    } 

基本上它採用DataServiceContext的Execute(URI)方法:http://msdn.microsoft.com/en-us/library/cc646700.aspx

如果您通過REST API調用查詢功能(例如PartitionKey eq'mypk'和RowKey ge'myrk'),您需要指定篩選條件。 不知道這是否是最好的解決方案:)期待對此發表評論。

+0

該過濾器是如何使用的? – starcorn 2012-08-09 14:12:12

+0

因此,假設您要查詢PartitionKey值「mypk」和大於「myrk」的RowKey值,您將如何爲過濾器定義值:PartitionKey eq「mypk」和RowKey ge「myrk」。我前一段時間寫了一篇博客文章,您可能會發現它很有用:http://www.cerebrata.com/Blog/post/Specifying-24filter-criteria-when-querying-Azure-Table-Storage-using-REST-API。 aspx – 2012-08-09 14:55:08

+0

請注意,儘管這有效,但您僅限於uri的長度(我不知道這是多長時間)。 – 2012-08-09 15:04:05

0

這是可能的,但它可能不是一個好主意。像這樣添加多個查詢參數總是會導致表掃描。這在一張小桌子裏可能沒問題,但是如果你的桌子很大,它會很慢。對於大型表格,您最好爲每個組合鍵運行單獨的查詢。

也就是說,你可以用一些LINQ魔術來建立一個動態查詢。下面是我用的,該輔助類:

public class LinqBuilder 
{ 
    /// <summary> 
    /// Build a LINQ Expression that roughly matches the SQL IN() operator 
    /// </summary> 
    /// <param name="columnValues">The values to filter for</param> 
    /// <returns>An expression that can be passed to the LINQ .Where() method</returns> 
    public static Expression<Func<RowType, bool>> BuildListFilter<RowType, ColumnType>(string filterColumnName, IEnumerable<ColumnType> columnValues) 
    { 
     ParameterExpression rowParam = Expression.Parameter(typeof(RowType), "r"); 
     MemberExpression column = Expression.Property(rowParam, filterColumnName); 

     BinaryExpression filter = null; 
     foreach (ColumnType columnValue in columnValues) 
     { 
      BinaryExpression newFilterClause = Expression.Equal(column, Expression.Constant(columnValue)); 
      if (filter != null) 
      { 
       filter = Expression.Or(filter, newFilterClause); 
      } 
      else 
      { 
       filter = newFilterClause; 
      } 
     } 

     return Expression.Lambda<Func<RowType, bool>>(filter, rowParam); 
    } 

    public static Expression<Func<RowType, bool>> BuildComparisonFilter<RowType, ColumnType>(string filterColumnName, Func<MemberExpression, BinaryExpression> buildComparison) 
    { 
     ParameterExpression rowParam = Expression.Parameter(typeof(RowType), "r"); 
     MemberExpression column = Expression.Property(rowParam, filterColumnName); 

     BinaryExpression filter = buildComparison(column); 
     return Expression.Lambda<Func<RowType, bool>>(filter, rowParam); 
    } 

}

你會使用它是這樣的:

var whereClause = BuildListFilter(queryColumnName, columnValues); 
CloudTableQuery<RowType> query = (from r in tableServiceContext.CreateQuery<MyRow>("MyTable") 
            where r.PartitionKey == partitionKey 
            select r) 
            .Where(whereClause) //Add in our multiple where clauses 
            .AsTableServiceQuery(); //Convert to table service query 
var results = query.ToList(); 

還要注意表服務強制執行的最大數量每個查詢約束。記錄的最大值是每個查詢15,但是當我最後一次嘗試(這是前一段時間)時,實際最大值爲14.

0

在表存儲中構建這樣的東西非常麻煩;類似於迫使圓形孔中的方形釘。

取而代之,您可以考慮使用Blob存儲來存儲您的博客和Lucene.NET,以實現您對標籤的搜索。 Lucene也允許更復雜的搜索,如(標籤=「A」和標籤=「B」和標籤!=「C」),此外還允許搜索博客文本本身,如果您願意的話。

http://code.msdn.microsoft.com/windowsazure/Azure-Library-for-83562538

2

您可以簡單構建where子句並傳遞到其中例如方法:

var whereClause="(PartitionKey eq 'Key1') and (PartitionKey eq 'Key2')" 

CloudStorageAccount storageAccount = CloudStorageAccount.Parse("AccountDetails"); 
      CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); 

      CloudTable table = tableClient.GetTableReference(<TableName>); 
      table.CreateIfNotExists(); 

      TableQuery<YourAzureTableEntity> query = 
       new TableQuery<YourAzureTableEntity>() 
        .Where(whereClause)); 
      var list = table.ExecuteQuery(query).ToList(); 
+0

+! 我想弄清楚如何通過Linq傳遞整個odata字符串,包括$ filter,$ top和$ select: https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices /查詢,表格和實體 – LastTribunal 2017-02-27 22:31:31