本文是在 《Azure 基础:Table storage》 一文的基础上介绍如何自定义 Azure Table storage 的查询过滤条件。如果您还不太清楚 Azure Table storage 的基本用法,请先移步前文

让我们回到前文中提到的一个问题,如何过滤出 MyLogTable 表中某一天产生的所有日志?在进入细节前我们先来回顾一下 MyLogTable 类的设计:

internal class MyLogEntity : TableEntity
{
public MyLogEntity() { }
public MyLogEntity(string pkey, string rkey)
{
this.PartitionKey = pkey;
this.RowKey = rkey;
}
//…
}

PartitionKey 用来存放产生日志的年份和月份(例如201607表示2016年7月),RowKey 用来存放产生日志的天和时分秒毫秒(例如160934248492表示16号9点34分…)。在我们设计的 MyLogTable 中,天信息保存在 RowKey 的前两位。我们要做的就是过滤 RowKey 的前两位,也就是找到所有 RowKey 以"xx"开头的记录。这在字符串操作中称为 StartsWith。遗憾的是现有 Table storage 的接口中没有提供这种功能的方法,因此我们需要自己实现它(还好 TableQuery 的实现支持我们去扩展它)!本文将通过实现 StartsWith 过滤条件说明如何自定义 Azure Table storage 的查询过滤条件。

TableQuery 类

TableQuery 是本文的主角,它代表了某个表上的一个查询。基本用法是使用查询条件构建一个 TableQuery 类的实例,然后把这个实例作为参数传递给 CloudTable 的ExecuteQuery 方法:

TableQuery<MyLogEntity> query = new TableQuery<MyLogEntity>().Where(
TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "")
);
var queryResult = logTable.ExecuteQuery(query);

我们还可以使用 TableQuery 的静态方法 CombineFilters 构建自定义的查询条件。比如我们要查询 PartitionKey 等于 "201607" 并且 RowKey 等于"161148372454"的记录:

TableQuery.CombineFilters(
TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, ""),
TableOperators.And,
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, "")
);

此时函数的返回结果为: "(PartitionKey eq '201607') and (RowKey eq '161148372454')"。
然后把这个过滤字符串送给 query.Where 函数做参数,或者设置给 query.FilterString 属性,就可以完成过滤功能了。
CombineFilters 方法可爱的地方在于我们可以不断的用它来合并查询条件,直到满意为止!

接下来我们一起看看 StartsWith 过滤条件的实现过程。

比较字符串

如何从一些字符串中找出以某个子串开头的字符串呢?我们可以从字符串的比较入手。
比如字符串具有下面的关系:

“abc”  ==  “abc” < “abd”
“abc” < “abca” < “abd”
“abc” < “abcz” < “abd”

由上面的大小关系我们可以得出结论:以"abc"开头的字符串必定大于或等于"abc"且小于"abd"。OK,这就是我们构建 StartsWith 过滤条件的理论基础。

构建 StartsWith 过滤条件

接下来我们通过 TableQuery.CombineFilters 方法构建 StartsWith 过滤条件:

string startsWithCondition = TableQuery.CombineFilters(
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThanOrEqual, "abc"),
TableOperators.And,
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThan, "abd")
);

TableQuery.CombineFilters 方法的返回值是一个字符串。运行上面的代码我们会得到字符串:

"(RowKey ge 'abc') and (RowKey lt 'abd')"

我们完全可以手动拼出这样的字符串,但我相信没有程序猿愿意这么干。所以我们要继续完善上面的方法:

string startStr = "abc";
int endIndex = startStr.Length - ;
Char lastChar = startStr[endIndex];
// 找到比字符'c'大的那个字符。
Char afterLastChar = (char)(lastChar + );
// 拼出字符串 "abd"
string endStr = startStr.Substring(, endIndex) + afterLastChar;
string startsWithCondition = TableQuery.CombineFilters(
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThanOrEqual, startStr),
TableOperators.And,
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThan, endStr)
);

组合更多过滤条件

在前面构建 StartsWith 过滤条件时我们已经使用 TableQuery.CombineFilters 方法组合了不同的过滤条件。遗憾的是 TableQuery.CombineFilters 方法只有两个参数的重载,我们不能添加更多的 TableOperators 操作。

但我们可以继续调用 TableQuery.CombineFilters 方法去组合上一个结果和新的条件。比如我们要把 Startswith 过滤条件和 PartitionKey 过滤条件组合起来就可以这么干:

string filterCondition = TableQuery.CombineFilters(
TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, ""),
TableOperators.And,
"(RowKey ge 'abc') and (RowKey lt 'abd')"
);

运行上面的代码,生成的结果为:

(PartitionKey eq '') and ((RowKey ge 'abc') and (RowKey lt 'abd'))

到这来就很清楚了,TableQuery.CombineFilters 方法的主要工作就是把过滤条件组织成查询引擎能够识别的字符串。因而我们可以通过不断的叠加生成很复杂的过滤条件。

封装 StartsWith 过滤条件

下面我们把 StartsWith 的逻辑封装到 StartsWithByRowKey 类型中,下面是完整的代码:

public class MyLogEntity : TableEntity
{
public MyLogEntity() { }
public MyLogEntity(string pkey, string rkey)
{
this.PartitionKey = pkey;
this.RowKey = rkey;
} public DateTime LogDate { get; set; }
public string LogMessage { get; set; }
public string ErrorType { get; set; }
} public class StartsWithByRowKey : IQuery<CloudTable, List<MyLogEntity>>
{
private readonly string partitionKey;
private readonly string startsWithString;

internal StartsWithByRowKey(string partitionKey,
string startsWithString)
{
this.partitionKey = partitionKey;
this.startsWithString = startsWithString;
} public List<MyLogEntity> Execute(CloudTable coludTable)
{
var query = new TableQuery<MyLogEntity>(); int endIndex = startsWithString.Length - ;
Char lastChar = startsWithString[endIndex];
Char afterLastChar = (char)(lastChar + );
string endStr = startsWithString.Substring(, endIndex) + afterLastChar; string startsWithCondition = TableQuery.CombineFilters(
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThanOrEqual, startsWithString),
TableOperators.And,
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThan, endStr)
); string filterCondition = TableQuery.CombineFilters(
TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey),
TableOperators.And,
startsWithCondition
); var entities = coludTable.ExecuteQuery(query.Where(filterCondition));
return entities.ToList();
}
} public interface IQuery<in TModel, out TResult>
{
TResult Execute(TModel model);
}

应用 StartsWith 的实例

现在查询 PartitionKey 为"201607",RowKey 以"16"开头的记录可以这么写:

StartsWithByRowKey myStartsWithQuery = new StartsWithByRowKey("", "");
List<MyLogEntity> result = myStartsWithQuery.Execute(logTable);

代码简洁了很多,读起来也更清晰了(您还可以动手给 PartitionKey 也添加同样的功能)!

总结

本文简单的介绍了 TableQuery 类型,然后比较详细的说明了 StartsWith 过滤条件的思路及实现。主要是想通过 StartsWith 的实现来说明如何利用现有的类型及方法来实现自定义查询的过滤条件。对于有类似需求的朋友,希望能起到抛砖引玉的作用。

Azure 基础:自定义 Table storage 查询条件的更多相关文章

  1. Azure 基础:Table storage

    Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob.Queue.File 和 Table.其中的 Table 就是本文的主角 Azure Tabl ...

  2. Azure 基础:Blob Storage

    Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob.Queue.File 和 Table. 笔者在前文中介绍了 Table Storage 的基本 ...

  3. 自定义 Azure Table storage 查询过滤条件

    本文是在Azure Table storage 基本用法一文的基础上,介绍如何自定义 Azure Table storage 的查询过滤条件.如果您还不太清楚 Azure Table storage ...

  4. Azure 基础:Queue Storage

    Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob.Queue.File 和 Table. 笔者在前文中介绍了 File Storage 的基本用 ...

  5. Azure 基础:File Storage

    Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob.Queue.File 和 Table. 笔者在前文中介绍了 Blob Storage 的基本用 ...

  6. JEECG中datagrid方法自定义查询条件

    自定义加添加查询条件的用法: CriteriaQuery cq = new CriteriaQuery(EquipmentEntity.class, dataGrid); //查询条件组装器 org. ...

  7. Windows Azure Table Storage 解决 Guid 查询问题

    在使用 Windows Azure Table Storage 的 CloudTableClient 对Azure 进行数据查询时,会发现在自定义类的Guid类型始终无法去成功查询出数据,对比发现 G ...

  8. Azure Storage 系列(四)在.Net 上使用Table Storage

    一,引言 今天我们就不多说废话了,直接进入正题,Azure Table Storage.开始内容之前,我们先介绍一下Azure Table Storage. 1,什么是Azure Table Stor ...

  9. Azure Table storage 基本用法 -- Azure Storage 之 Table

    Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob.Queue.File 和 Table,其中的 Table 就是本文的主角 Azure Tabl ...

随机推荐

  1. linux信息收集篇之sosreport

    sosreport是一个类型于supportconfig 的工具,sosreport是python编写的一个工具,适用于centos(和redhat一样,包名为sos).ubuntu(其下包名为sos ...

  2. 清空数据库错误:因为该表正由 FOREIGN KEY 约束引用 解决办法

    如下解决了五个问题 1. 清空数据 2. 有外键也可以, 因为是逆向删除, 从最后一张表删除. 且使用的是delete, 因为truncate不能对有外键的表 3. 种子问题, 如果表存在种子重设为0 ...

  3. Questions about UIUC and USC

    Questions about UIUC and USC I am admitted to University of Illinois at Urbana-Champaign (UIUC) Prof ...

  4. [BZOJ 1568][JSOI2008]Blue Mary开公司

    [BZOJ 1568][JSOI2008]Blue Mary开公司 题意 \(n\) 次操作, 维护一个一次函数集合 \(S\). 有两种操作: 给定 \(b\) 和 \(k\), 向 \(S\) 中 ...

  5. SDN2017 第五次实验作业

    实验目的 1.搭建如下拓扑并连接控制器 2.下发相关流表和组表实现负载均衡 3.抓包分析验证负载均衡 实验步骤 建立以下拓扑,并连接上ODL控制器. 利用ODL下发组表.流表,实现建议负载均衡 s1组 ...

  6. Phoenix安装配置

    下载Phoenix     在网站http://phoenix.apache.org/download.html找到对应HBase版本的安装程序,并下载安装包,解压安装程序到指定目录 [root@ha ...

  7. CountUp.js用法 让数字动起来的插件

    CountUp.js 无依赖的.轻量级的 JavaScript 类,可以用来快速创建以一种更有趣的动画方式显示数值数据.尽管它的名字叫 countUp,但其实可以在两个方向进行变化,这是根据你传递的 ...

  8. Java POI单元格使用心得

    1: /** * Created by liuguangxin on 2018/5/16. * <p> * MergeRegion:表示excel中cell的信息,startRow与end ...

  9. RMAN删除备份

    删除备份--DELETE命令 用于删除RMAN备份记录及相应的物理文件.当使用RMAN执行备份操作时,会在RMAN资料库(RMAN Repository)中生成RMAN备份记录,默认情况下RMAN备份 ...

  10. Python2.7-csv

    csv模块,用于读写 csv 文件,常用 reader 和 writer 对象进行操作 1.模块的类 1.1 Dialect 对象,设置 csv 文件的各种格式,包括分隔符,引用符,转义符等 1.1. ...