【问题标题】:Multiple filter conditions Azure table storage多个筛选条件 Azure 表存储
【发布时间】:2013-09-04 03:58:58
【问题描述】:

如何在 Azure 表存储上设置多个筛选器?

这是我尝试过的:

string partitionFilter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "partition1");
string date1 = TableQuery.GenerateFilterCondition("Date", QueryComparisons.GreaterThanOrEqual, "31-8-2013T14:15:14Z");
string date2 = TableQuery.GenerateFilterCondition("Date", QueryComparisons.LessThanOrEqual, "31-8-2013T14:15:14Z");
string finalFilter = TableQuery.CombineFilters(partitionFilter, TableOperators.And, date1);

这不起作用,因为TableQuery.CombineFilters() 只需要 3 个参数。而且我需要一个额外的参数用于第二个日期。

我的第二次尝试:

string filter = "PartitionKey eq 'partition1' and Date ge datetime'31-8-2013T14:15:14Z' and Date lt datetime'31-8-2013T14:19:10Z'";
TableQuery<CustomEntity> query = new TableQuery<CustomEntity>().Where(filter).Take(5);

这将返回 400 bad request。但是,如果我删除“日期时间”,它会运行但不返回任何结果,而它应该返回几 100 条记录。

根据来自 msdn 的this doc,这就是日期时间的格式。

我的结果应该是两个日期之间的所有记录。

我怎样才能做到这一点?

【问题讨论】:

    标签: c# azure azure-table-storage


    【解决方案1】:

    只是处理一个没有过滤器并且基于@LivingOnACloud的新查询的情况,我宁愿这样写:

     public static TableQuery<TElement> AndWhere<TElement>(this TableQuery<TElement> query, string filter)
                where TElement : ITableEntity,new ()
            {
                if (query.FilterString.IsNullOrEmpty())
                {
                    query.FilterString =  filter;
                }
                else
                {
                    query.FilterString = TableQuery.CombineFilters(query.FilterString, TableOperators.And, filter);
                }
                return query;
            }
    

    其余的都遵循相同的检查,事情会变得更好。

    【讨论】:

      【解决方案2】:

      首先用其中一个日期过滤器“和”您的分区过滤器,然后用另一个日期过滤器“和”中间结果。

      string date1 = TableQuery.GenerateFilterConditionForDate(
                         "Date", QueryComparisons.GreaterThanOrEqual,
                         DateTimeOffsetVal);
      string date2 = TableQuery.GenerateFilterConditionForDate(
                         "Date", QueryComparisons.LessThanOrEqual,
                         DateTimeOffsetVal);
      string finalFilter = TableQuery.CombineFilters(
                              TableQuery.CombineFilters(
                                  partitionFilter,
                                  TableOperators.And,
                                  date1),
                              TableOperators.And, date2);
      

      【讨论】:

      • 我尝试了您的解决方案,它可以编译并运行,但没有返回任何记录。对于您知道的DateTime 比较,我有什么特别的“事情”吗?
      • 您所做的过滤器的每种数据类型似乎都有不同的枚举。日期是TableQuery.GenerateFilterConditionForDate。这成功了。达米特,你能在你的答案中也设置这个吗?
      【解决方案3】:

      我正在使用Windows Azure Storage 7.0.0,您可以使用 Linq 查询,这样您就不需要再组合过滤器了:

      // filter dates for test
      var startDate = DateTime.Parse("01/02/2016 12:00:00 AM"); 
      var endDate = DateTime.Parse("02/02/2016 12:00:00 AM");
      
      // Get the cloud table
      var cloudTable = GetCloudTable();
      
      // Create a query: in this example I use the DynamicTableEntity class
      var query = cloudTable.CreateQuery<DynamicTableEntity>()
              .Where(d => d.PartitionKey == "partition1"
                     && d.Timestamp >= startDate && d.Timestamp <= endDate);
      
      // Execute the query
      var result = query.ToList();
      

      这是生成的查询:

      (((PartitionKey eq 'partition1') and (Timestamp ge datetime'2016-01-31T11:00:00Z')) and (Timestamp le datetime'2016-02-01T11:00:00Z')

      你可以注意到:

      • 过滤器已合并。
      • 日期已转换为 UTC。

      【讨论】:

      • 查询中是否提供了分区和行键(如果使用)的硬性要求?否则,我如何确保我没有扫描整个表?
      • @CamHart 如果不指定 PartitionKey 和 RowKey,则将执行表扫描
      【解决方案4】:

      如何在 Azure 表存储上设置多个筛选器?

      我也在想同样的事情。我为 TableQuery 类编写了一个扩展,它运行良好。

      这是一个简单的更改,这让我想知道我们是否会错误地使用多个过滤器进行查询。

      public static class TableQueryExtensions 
      {
          public static TableQuery<TElement> AndWhere<TElement>(this TableQuery<TElement> @this, string filter)
          {
              @this.FilterString = TableQuery.CombineFilters(@this.FilterString, TableOperators.And, filter);
              return @this;
          }
      
          public static TableQuery<TElement> OrWhere<TElement>(this TableQuery<TElement> @this, string filter)
          {
              @this.FilterString = TableQuery.CombineFilters(@this.FilterString, TableOperators.Or, filter);
              return @this;
          }
      
          public static TableQuery<TElement> NotWhere<TElement>(this TableQuery<TElement> @this, string filter)
          {
              @this.FilterString = TableQuery.CombineFilters(@this.FilterString, TableOperators.Not, filter);
              return @this;
          }
      }
      

      【讨论】:

      • 如果您要添加多个Or 过滤器,那么FilterString 将看起来像((() or (Foo eq '1')) or (Foo eq '2')) or (Foo eq '3')。如果FilterString 为空,则仅添加过滤器本身:@this.FilterString = @this.FilterString == null ? filter : TableQuery.CombineFilters(@this.FilterString, TableOperators.Or, filter);
      【解决方案5】:

      只是想再添加一个答案。

      string filter = "PartitionKey eq 'partition1' and Date ge datetime'31-8-2013T14:15:14Z' and Date lt datetime'31-8-2013T14:19:10Z'";
      TableQuery<TablePost> query = new TableQuery<TablePost>().Where(filter).Take(5);
      

      上面的原因代码失败是因为日期/时间值必须以yyyy-MM-ddTHH:mm:ssZ 格式输入。所以你的查询应该是:

      string filter = "(PartitionKey eq 'partition1') and (Date ge datetime'2013-08-31T14:15:14Z' and Date lt datetime'2013-08-31T14:19:10Z')";
      TableQuery<TablePost> query = new TableQuery<TablePost>().Where(filter).Take(5);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-08
        • 2013-01-02
        • 1970-01-01
        • 2018-02-01
        • 2013-08-01
        • 2016-11-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多