本文是在 《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. 反向代理负载均衡调度:nginx

    一.概述 反向代理:以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个 ...

  2. net.exe use命令的使用

    net.exe use 查看当前的连接 net.exe use * /del /y 断开所有连接 net.exe use \\server\share "password" /us ...

  3. ASA 用TFTP 备份配置方法

    一种方法是用ASDM,在菜单样哪项里有一个backup,保存为一个压缩文件rar,恢复也是用ASDM.另一种是用TFTP SERVER 来做,电脑用网线接上ASA,还要把cisco TFTP SERV ...

  4. yum安装某个包出现冲突的情况

    yum安装是非常方便的,可以自动解决依赖问题,但是有时候我们安装包会出现冲突,这个时候我们就要查找是哪些包与哪些包出现冲突,然后再针对性的解决问题. 一般来说起冲突的包会报出来,主要为两点 1.包与包 ...

  5. 在阿里云Windows Server 上部署ASP .NET CORE2.0项目

    近期使用ASP.NET Core2.0对博客进行了重写,在部署到服务器时遇到了一些问题,来记录一下留用. 配置环境 安装 .Net Framework3.5 在IIS管理器上直接开启,这里总是失败,上 ...

  6. DAU、UV、独立IP、PV的区别和联系

    基本概念 DAU(Daily Active User)日活跃用户数量.常用于反映网站.互联网应用或网络游戏的运营情况.DAU通常统计一日(统计日)之内,登录或使用了某个产品的用户数(去除重复登录的用户 ...

  7. PyQt5--QCalendar

    # -*- coding:utf-8 -*- ''' Created on Sep 20, 2018 @author: SaShuangYiBing Comment: ''' import sys f ...

  8. Android安全测试

  9. Dubbo -- 系统学习 笔记 -- 安装手册

    安装手册 示例提供者安装 示例消费者安装 Zookeeper注册中心安装 Redis注册中心安装 简易注册中心安装 简易监控中心安装 管理控制台安装 推荐使用Zookeeper注册中心 你可以只运行D ...

  10. OpenCV——直方图计算、寻早最值位置和对比匹配(判断两幅图的相似程度)