上云都能获得哪些好处?可以享受到几乎无穷无尽的低成本、大容量、高灵活性云服务,恐怕每个人心里都想着“真香”。然而这也会造成一些问题,以云存储服务为例,各种文件都可以一股脑丢到云存储服务中安全、妥善地保存,但当你需要从中找到某个文件时,面对TB甚至PB级别的云存储空间,你准备怎么做……

云对象存储服务的出现,以其灵活的弹性和可扩展性,以及卓越性价比,促使越来越多的场景开始使用云对象存储解决方案。从大数据场景到企业数据备份/存储场景,越来越多开源软件和商业软件都支持云对象存储架构。

然而由于对象存储区别于传统的文件存储系统的本质,使其原生就不支持文件基于索引的检索查询。因此当用户将大量数据文件存放在对象存储服务中,如何管理这些文件并建立数据目录(inventory),进而提供类似文件系统的索引检索查询成为很多用户面临的问题。

本文我们将为大家介绍一些微软云对象存储Azure Blob的文件索引检索查询解决方案。

图片

三种使用场景,各有其解决方案

我们可以把文件索引检索查询的对象分为:文件名、文件元数据,以及文件内容三个类别。对于不同检索查询对象,可以选择不同方式进行支持。

例如通常在文件名的索引查询上,用户会依赖于模糊查询的方式来找到匹配的文件;而文件元数据内通常是一些键-值结构的数据,用户通常是通过自己定义标签逻辑来进行匹配查询;对于文件内容的搜索,通常是全文搜索,以及内容类型上富媒体的支持(如图片等)。

对于上述不同的场景我们可以考虑不同的方式来进行实现:

1、Blob文件名检索查询

RedisSearch、Elastic、Azure Search

2、Blob元数据检索查询

Azure Blob Indexing、RedisSearch、Elastic、Azure Search

3、Blob文件内容检索查询

Azure Search

下文我们将分别介绍每个场景下的解决方案。

1. 不同类型内容的检索查询思路

首先看看Blob文件名和元数据检索查询场景。对于元数据检索,Azure   Blob服务原生支持在数据文件之上添加元数据(Metadata),通过元数据,用户可以获得Blob文件的基础信息。通常元数据都是通过键-值(Key-Value)的方式存储,而对于“文件名”,我们可以理解为一个一维的元数据。

例如,设想一个电子书场景:每个Blob文件为一个电子书文件,可以在元数据中存放电子书的作者、发行日期、类别和摘要信息等。在使用这些信息时,通常用户可能通过电子书的书名、作者、类别等信息查询检索匹配的电子书名单。

对于查询检索,通常会有两种情况:完全匹配和模糊查询。对于完全匹配的明确查询,用户需要准确地选择或输入查询的Key值,然后查询检索系统进行完全匹配返回。但有些情况下对于用户输入的准确性是很难管控的,这时模糊查询就可通过不完全匹配的方式来找到近似最优结果。

在Azure   Blob中原生提供了Blob   Indexing功能,支持典型的Key   Value检索查询。如果用户对于元数据的检索查询需求是完全匹配,Blob Indexing是一个非常好的方式,此时不需要额外借助其他外部系统来构建文件查询索引。

虽然Blob   Indexing的方式虽然简单易用,但也有场景限制,比如上面所述的模糊查询是无法通过Blob Indexing来做到的。目前Blob Indexing对于构建的Key Value都是按照String字符组数据类型来处理的,在查询检索时除支持等于匹配外也支持大于小于等匹配符,但由于Value按照字符串存储,所以对于大小匹配符的支持按照字母排序来进行比较,对于数字、日期等类型数据也是按照字符串来处理,所以对于大小匹配符的支持就会受限,同时对于数字类型数据的比较只支持第一个数字的比较(比如11和12比较,“>11”结果中不会有12)。

如果用户有数字比较的场景,建议把数字拆分成多个0-9位,创建多个Key   Value索引来实现(需要注意目前Azure Blob单个文件上最多支持10个Key   Value)。所以如果希望对元数据做模糊查询,可考虑通过RedisSearch、Elastic、Azure Search来构建外部查询索引,借助外部索引强大的搜索能力来进行支持,其中RedisSearch和Azure Research是微软提供第一方PaaS服务,可方便用户快速构建查询索引平台。

Azure Search作为微软自研的搜索产品,其对于微软第一方的服务原生集成是最大的优势,可以通过简单的点击将Blob数据信息导入到Azure   Search中。另外Azure   Search内的AI赋能可以增加对文件中富媒体内容的支持,这部分我们会在后面文件内容检索查询部分给大家单独介绍。

RedisSearch和ElasticSearch都是开源的索引查询产品,其中RedisSearch在微软云上的Redis   Enterprise Tier已经原生支持,客户可通过托管PaaS的方式快速创建使用,ElasticSearch客户可以通过Marketplace购买使用。

无论Azure   Blob Indexing还是外部查询索引系统(RedisSearch、ElasticSearch),用户都需要实时维护索引信息,当Blob文件进行增删改动作时,相应的需要对索引数据进行变更。整个系统架构的实现可以通过EventGrid来监听Blob的增删改动作,然后触发代码来进行索引的更新。对于索引变更的管理逻辑代码可通过托管在Azure Function服务中,快速的实现事件触发的逻辑。用户侧的查询可通过Webapp构建前端GUI层为用户提供访问。

图片

接下来再看看Blob文件内容检索查询。相较文件名和元数据场景,文件内容检索涉及的数据类型、文件类型兼容性至关重要。当前富媒体内容的爆发使得内容检索不仅限于文本,还可通过AI对富媒体内容进行识别标注,然后进行查询检索。微软云完整的认知服务套件,从文本、视觉、语音的全面支持可以帮助用户快速的数据赋能,Azure Search内置集成了Azure Cognitive认知服务,可快速对各类富媒体内容进行识别标注,并将结果数据导入到Azure Search中支撑检索查询。对于Azure上各类数据源的原生集成帮助用户可以快速对接各类原数据,让用户事半功倍。

图片

2. 上手Azure   Blob Indexing

在了解过Azure   Blob文件索引检索查询的几个典型场景后,接下来一起看看Azure Blob Indexing的方案实现。

首先回顾一下架构图,在Azure Blob中原生提供了Blob Indexing功能,支持典型的Key Value检索查询。如果用户对元数据的检索查询需求是完全匹配,Blob Indexing是一个非常好的方式,此时不需要额外借助其他外部系统来构建文件查询索引。

图片

目前Azure   Blob Indexing功能处于预览阶段,感兴趣的用户可在全球版Azure的Canada   Central、Canada   East、France   Central和France   South这几个区域创建。创建时需要选择General Purpose V2 Storage Account(且不开启Hierachical namespace)。具体创建过程可以访问这里查阅,本文不再赘述。在整个方案中,我们需要通过代码来维护Blob Indexing中的索引数据,下面来看一下代码的实现。

数据准备:示例中通过本地的书籍信息样本数据为大家进行介绍,原数据是一个CSV文件,文件中包含如下书籍信息:

图片

运行环境准备:示例中采用Python作为示例代码,环境中需要安装azure-storage-blob依赖包,并从Azure门户读取Blob服务的链接字符串。

from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient

import csv
AZURE_STORAGE_CONNECTION_STRING="Input_your_blob_connectionstring_here"
# Create Blob Client
blob_service_client = BlobServiceClient.from_connection_string(AZURE_STORAGE_CONNECTION_STRING)
# Create a unique name for the containercontainer_name = "indexdemo"
# Create the containercontainer_client = blob_service_client.create_container(container_name)
数据索引:通过读取CSV文件中的数据信息,仿真创建Blob,并将作者、书名、发行商和发行时间作为索引数据。
data = "demo"
with open('demobookdataset.csv', mode='r') as csv_file:    csv_reader = csv.DictReader(csv_file)    line_count = 0    for row in csv_reader:        if line_count == 0:            print(f'Column names are {", ".join(row)}')            line_count += 1            continue
        # Create a blob client using the local file name as the name for the blob        blob_client = blob_service_client.get_blob_client(container=container_name, blob=str(line_count))
        # Upload blob Data        blob_client.upload_blob(data)
        # Preparing Index Key Value Data        tagmark = {}        tagmark["author"] = row["authors"]        tagmark["title"] = row["title"]        tagmark["publisher"] = row["publisher"]        tagmark["publicationdate"] = row["publication_date"]
        # Set Blob Indexing        blob_client.set_blob_tags(tagmark)        line_count += 1
数据检索查询:示例中通过以索引中author作为查询值进行检索查询验证,需要注意在Filter的查询语句编写语法上需要按照规范进行编写,可以参考查询语法进行定义。
# Full loop all the documents indexwith open('demobookdataset.csv', mode='r') as csv_file:    csv_reader = csv.DictReader(csv_file)    line_count = 0    for row in csv_reader:        if line_count == 0:            #print(f'Column names are {", ".join(row)}')            line_count += 1            continue        filter = "\"author\" = '" + row["authors"] + "'"        result = blob_service_client.find_blobs_by_tags(filter)        for item in result:            print(item)
通过上述示例我们了解到Blob Indexing的代码实现,大家可以按照自己喜好的开发语言进行开发。

3. RedisSearch的实现

上文曾经提到过,我们可以选择RedisSearch作为索引数据查询引擎,或者可以采用相同的架构使用ElasticSearch进行搭建(RedisSearch功能已在海外Azure Redis Cache Enterprise版本中支持,该版本为RedisLabs发布的Redis商业版本,包含很多Redis商业版功能,RedisSearch插件支持也是其中之一)。

RedisSearch全面支持检索查询功能,包含模糊搜索、全文检索、丰富的索引数据类型支持,以及灵活的查询检索语法。目前Redis Cache Enterprise Tier已在海外Azure预览,用户可参考这里进行创建,此处不做赘述。下面我们主要聚焦RedisSeach索引数据的创建和管理逻辑。

数据准备:示例中通过本地书籍信息样本数据为大家介绍,原数据是一个CSV文件,文件中包含如下书籍信息:

图片

运行环境准备:示例中采用Python作为示例代码,环境中需要安装redisearch-py依赖包,并从Azure门户读取Redis Cache   Enterprise实例的链接字符串。

from redisearch import Client, TextField, NumericField, Query, resultimport timeimport datetimeimport csv
redishost = 'input_your_redis_fqdn_here'redisport = 10000redispassword = 'input_your_redis_accesskey_here'
# Creating a client with a given index nameclient = Client("searchdemo", host=redishost, port=redisport, password=redispassword)
# Creating the index definition and schemaclient.create_index([TextField('author'), TextField('title'), TextField('publisher'), NumericField('publicationdate', sortable=True)], stopwords=[])
数据索引:通过读取CSV文件中的数据信息,仿真创建Blob并将作者、书名、发行商和发行时间作为索引数据。​​​
with open('demobookdataset.csv', mode='r') as csv_file:    csv_reader = csv.DictReader(csv_file)    line_count = 0    for row in csv_reader:        if line_count == 0:            print(f'Column names are {", ".join(row)}')            line_count += 1            continue        if int(row["publication_date"].split('/')[2]) >= 1970:            publishdate = time.mktime(datetime.datetime.strptime(row["publication_date"], "%m/%d/%Y").timetuple())        else:            epoch = datetime.datetime(1970, 1, 1)            t = datetime.datetime.strptime(row["publication_date"], "%m/%d/%Y")            diff = t-epoch            publishdate = diff.days * 24 * 3600 + diff.seconds                # Indexing a document        client.add_document(str(line_count), author = row["authors"], title = row["title"], publisher = row["publisher"], publicationdate = publishdate)        line_count += 1
数据检索查询:示例中通过以索引中author作为查询值进行检索查询验证,需要注意在Filter的查询语句编写语法上需要按照规范进行编写,可以参考查询语法进行定义。
filter = "create_your_filter_here"result = client.search(filter)for item in result.docs:    print(item)
至此,我们的所有工作就已全部完成。

RedisSearch支持丰富的检索查询语法,用户可灵活定义查询逻辑,而大家也可以参考上述查询语法进行深入的学习来定义自己的场景。

上述示例通过Python代码实现,大家可按照自己喜好的开发语言进行开发,整个方案关于EventGrid、Function的集成这里就不再赘述,感兴趣的小伙伴可以点击文末阅读原文,参考其他相关文档。

通过这些简单的操作,写几行代码,就可以借助Azure提供的一系列服务,为你的Blob存储构建一个功能完善、操作简单的“搜索引擎”。欢迎自行上手体验。如果希望了解有关Azure服务的其他有趣、实用的玩法,也欢迎在评论中提出。祝大家上云愉快!

  图片

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐