自定义 Azure Table storage 查询过滤条件
本文是在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 是本文的主角,它代表了 Table 上的一个查询。基本用法是使用查询条件构建一个 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 '201607') 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 Blob Storage 基本用法 -- Azure Storage 之 Blob
Azure Queue Storage 基本用法 -- Azure Storage 之 Queue
Azure File Storage 基本用法 -- Azure Storage 之 File
Azure Table storage 基本用法 -- Azure Storage 之 Table
自定义 Azure Table storage 查询过滤条件的更多相关文章
- Azure 基础:自定义 Table storage 查询条件
本文是在 <Azure 基础:Table storage> 一文的基础上介绍如何自定义 Azure Table storage 的查询过滤条件.如果您还不太清楚 Azure Table s ...
- Windows Azure Table Storage 解决 Guid 查询问题
在使用 Windows Azure Table Storage 的 CloudTableClient 对Azure 进行数据查询时,会发现在自定义类的Guid类型始终无法去成功查询出数据,对比发现 G ...
- Azure Table storage 基本用法 -- Azure Storage 之 Table
Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob.Queue.File 和 Table,其中的 Table 就是本文的主角 Azure Tabl ...
- Azure Table Storage(一) : 简单介绍
Azure Table Storage是什么: Azure Table Storage是隶属于微软Azure Storage这个大服务下的一个子服务, 这个服务在Azure上算是老字号了, 个人大概在 ...
- Azure Table storage 之改进DynamicTableEntity类为其添加动态语言扩展
在之前的一篇文章中提到,storage类库中包含一个可以用来动态获取Azure table storage 表结构的类-DynamicTableEntity. 我们可以通过这个类,我们无需为每一个表提 ...
- Windows Azure Table storage 之 动态Table类 DynamicTableEntity
在一般情况下,当我们在.net中使用Azure table storage的时候都会为该表建立一个TableEntity的派生类,如下所示. public class CustomerEntity : ...
- mysql 关联条件与查询(过滤)条件
mysql用outer join时 on 后边只是关联条件,有时可能会查出无用的记录, 需用where查询条件过滤 五欧诺个的数据. 记录一下
- Hibernate @OneToMany等注解设置查询过滤条件等
1.如实体PdOrg对象中有users对象,数据库user表有字段DEL_FLAG(0:删除:1:未删除): private List<User> users= new ArrayList ...
- hibernate @OneToMany等注解设置查询过滤条件
如实体PdOrg对象中有users对象,数据库user表有字段DEL_FLAG(0:删除:1:未删除): private List<User> users= new ArrayList&l ...
随机推荐
- Excel导入-----导出(包含所选和全部)操作
在做系统的时候,很多时候信息量太大,这时候就需要进行Excel表格信息的导入和导出,今天就来给大家说一下我使用Excel表格信息导入和导出的心得. 1:首先需要在前端显示界面View视图中添加导入Ex ...
- Jquery插件开发精品教程
最开始接触jquery对他提供的各种插件总是十分有兴趣,但是总是不理解为什么这样写,从网络上查询了很久终于找到这篇文章,讲解的很详细,分享给大家. 要说jQuery 最成功的地方,我认为是它的可扩展性 ...
- Get&Post简单说明
一.GET请求和POST请求简单说明 创建GET请求 1 // 1.设置请求路径 2 NSString *urlStr=[NSString stringWithFormat:@"http:/ ...
- 理解Java Integer的缓存策略
转载自http://www.importnew.com/18884.html 本文将介绍 Java 中 Integer 缓存的相关知识.这是 Java 5 中引入的一个有助于节省内存.提高性能的特性. ...
- CentOS 7 系统的初始划配置
(1).主机名的更改 •临时生效:hostname 主机名 •永久生效:hostnamectl set-hostname 主机名 (2).网络的配置 •临时生效:ifconfig 网卡名 IP地址 ...
- wap,h5页面
网址: 1:天猫(http://m.tmall.com) 2:淘宝(http://m.taobao.com) 3:京东(http://m.jd.com) 4:网易(http://3g.163.com) ...
- struts2是如何加载相关的package元素节点信息的
这不是一篇纯技术文章,而是一篇分享我个人在前后端分离路上收获的点点滴滴的文章,以此来为准备尝试前后端分离或者想了解前后端分离的童鞋做一个大体的讲解. 上一家公司是家小公司,做了一年的全栈开发,对前端的 ...
- 二叉搜索树、B树
二叉搜索树又叫二叉排序树. B树又可写为B-树,“B-树”种的“-”无区分意义. 此外,还有B+树,B*树.
- Sublime+Golang Plugin
很喜欢在Sublime开发Golang程序,主要是要一个Sublime Golang Plugin, 可以给代码autocomplement.相当的棒! 1.安装Sublime https://www ...
- 尝试u3d中将代码与编辑器分离
最近与朋友交流,他一直是做端游,最近接触了u3d以后无法忍受代码与配置文件,美术资源全部纠缠在一起的状况,于是一直在琢磨怎么将编辑器与代码彻底分离. 自己也抽空研究一下,碰到一些问题先记录下来. 首先 ...