标量检索是OSS提供的基于Object元数据的索引功能,允许您自定义条件,快速筛选并获取Object列表。可以帮助您更好地管理与了解数据结构,方便您后续查询、统计和管理Object。
使用场景
数据审计场景
通过标量检索,您可以快速定位文件,以满足数据审计或监管需求。例如,在金融服务行业,您可以通过自定义标签、访问权限等元数据进行筛选,从而找到具有特定敏感性级别或特定权限的文件,以提升数据审计的效率。
企业备份与归档场景
企业在进行数据备份和归档时,可以利用标量检索,例如根据文件的创建时间、存储类型或自定义标签等元数据,迅速检索到特定日期或类型的文件,从而快速恢复历史数据或归档记录。
注意事项
地域限制
华东1(杭州)、华东2(上海)、华北1(青岛)、华北2(北京)、华北3(张家口)、华南1(深圳)、华南3(广州)、西南1(成都)、中国香港、新加坡、印度尼西亚(雅加达)、德国(法兰克福)、美国(弗吉尼亚)、美国(硅谷)、英国(伦敦)地域的Bucket支持使用标量检索功能。
Bucket限制
默认只支持为文件数量在100亿以下的Bucket开启标量检索功能。
费用说明
标量检索目前是公测阶段。使用标量检索功能会产生Object的元数据管理费用以及检索次数费用,但公测期间暂不收费。关于标量检索计费项的更多信息,请参见数据索引费用。
除标量检索计费项外,使用标量检索还会产生API请求费用,按照API调用次数收费。涉及的API请求如下:
行为
API
次数
为Bucket中的文件构建索引
HeadObject
每个文件调用1次
Bucket中文件存在Tag
GetObjectTag
每个携带Tag的文件调用1次
Bucket中存在软链接文件
GetSymlink
每个携带软链接的文件调用1次
扫描Bucket中的文件
ListObjects
每扫描1000个文件调用1次
关于OSS API的请求费用,请参见请求费用。
建立索引所需时间
开启标量检索功能时,建立索引所需时间与Bucket内存量的文件数量成正比。文件数量越多,建立索引的时间越长。 一般来说,1000万个文件初次建立索引的时间约为1小时,10亿个文件初次建立索引的时间约为1天,100亿个文件初次建立索引的时间约为2~3 天,该时间仅供参考。
分片上传
对于通过分片上传生成的Object,查询结果中只显示已通过CompleteMultipartUpload操作将碎片(Part)合成的完整Object,不显示已初始化但未完成(Complete)或者未中止(Abort)的碎片。
操作步骤
使用OSS控制台
以查找所有文件大小小于500KB,最后更新时间在2024年9月11日0:00至2024年9月12日0:00的文件,输出结果按文件大小升序排列,并按文件大小统计最大值为例:
Bucket为广州地域
登录OSS管理控制台。
单击Bucket 列表,然后单击目标Bucket名称。
在左侧导航栏, 选择文件管理 > 数据索引。
在数据索引页面,单击立即开启。
选择标量检索,单击确认开启。
说明开启标量检索需要等待一定的时间,具体等待时长取决于Bucket中Object的数量。
按以下说明设置OSS元数据检索条件,其他参数保留默认设置。
将最后修改时间设置为2024年9月11日0:00至2024年9月12日0:00。
文件大小设置为小于500KB。
设置输出方式。
对象排序方式选择按照文件大小升序排列。
数据聚合选择按照文件大小的最大值聚合输出。
单击立即查询。符合检索条件的所有文件共2个,如下图所示,文件最大为434KB。
如需了解完整的检索条件和输出设置,请参见检索条件及输出设置。
Bucket为杭州、上海、青岛、北京、张家口、深圳、成都、中国香港、新加坡、雅加达、法兰克福、弗吉尼亚、硅谷、伦敦地域
登录OSS管理控制台。
单击Bucket 列表,然后单击目标Bucket名称。
在左侧导航栏, 选择文件管理 > 数据索引。
开启元数据管理。
说明开启元数据管理需要等待一定的时间,具体等待时长取决于Bucket中Object的数量。
按以下说明设置对象基础过滤条件,其他参数保留默认设置。
将最后修改时间设置为2024年9月11日0:00至2024年9月12日0:00。
文件大小设置为小于500KB。
展开更多过滤条件。
对象排序方式选择按照文件大小升序排列。
数据聚合选择按照文件大小的最大值聚合输出。
单击查询。符合检索条件的所有文件共2个,如下图所示,文件最大为434KB。
如需了解完整的检索条件和输出设置,请参见检索条件及输出设置。
使用阿里云SDK
仅Java SDK、Python SDK以及Go SDK支持通过标量检索功能查询满足指定条件的Object。使用标量检索功能前,您需要为指定Bucket开启元数据管理功能。关于标量检索的代码示例,请参见SDK简介。
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import java.util.ArrayList;
import java.util.List;
public class Demo {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
private static String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 填写Bucket名称,例如examplebucket。
private static String bucketName = "examplebucket";
public static void main(String[] args) throws Exception {
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
String region = "cn-hangzhou";
// 创建OSSClient实例。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
// 查询满足指定条件的文件(Object),并按照指定字段和排序方式列举文件信息。
int maxResults = 20;
// 指定查询小于1048576字节的文件,且最多返回20个结果,返回结果按升序排列。
String query = "{\"Field\": \"Size\",\"Value\": \"1048576\",\"Operation\": \"lt\"}";
String sort = "Size";
DoMetaQueryRequest doMetaQueryRequest = new DoMetaQueryRequest(bucketName, maxResults, query, sort);
Aggregation aggregationRequest = new Aggregation();
Aggregations aggregations = new Aggregations();
List<Aggregation> aggregationList = new ArrayList<Aggregation>();
// 指定聚合操作的字段名称。
aggregationRequest.setField("Size");
// 指定聚合操作的操作符,max表示最大值。
aggregationRequest.setOperation("max");
aggregationList.add(aggregationRequest);
aggregations.setAggregation(aggregationList);
// 设置聚合操作。
doMetaQueryRequest.setAggregations(aggregations);
doMetaQueryRequest.setOrder(SortOrder.ASC);
DoMetaQueryResult doMetaQueryResult = ossClient.doMetaQuery(doMetaQueryRequest);
if(doMetaQueryResult.getFiles() != null){
for(ObjectFile file : doMetaQueryResult.getFiles().getFile()){
System.out.println("Filename: " + file.getFilename());
// 获取标识Object的内容。
System.out.println("ETag: " + file.getETag());
// 获取Object的访问权限
System.out.println("ObjectACL: " + file.getObjectACL());
// 获取Object的类型。
System.out.println("OssObjectType: " + file.getOssObjectType());
// 获取Object的存储类型。
System.out.println("OssStorageClass: " + file.getOssStorageClass());
// 获取Object的标签个数。
System.out.println("TaggingCount: " + file.getOssTaggingCount());
if(file.getOssTagging() != null){
for(Tagging tag : file.getOssTagging().getTagging()){
System.out.println("Key: " + tag.getKey());
System.out.println("Value: " + tag.getValue());
}
}
if(file.getOssUserMeta() != null){
for(UserMeta meta : file.getOssUserMeta().getUserMeta()){
System.out.println("Key: " + meta.getKey());
System.out.println("Value: " + meta.getValue());
}
}
}
} else if(doMetaQueryResult.getAggregations() != null){
for(Aggregation aggre : doMetaQueryResult.getAggregations().getAggregation()){
// 获取聚合字段名称。
System.out.println("Field: " + aggre.getField());
// 获取聚合字段的操作符。
System.out.println("Operation: " + aggre.getOperation());
// 获取聚合操作的结果值。
System.out.println("Value: " + aggre.getValue());
if(aggre.getGroups() != null && aggre.getGroups().getGroup().size() > 0){
// 获取分组聚合的值。
System.out.println("Groups value: " + aggre.getGroups().getGroup().get(0).getValue());
// 获取分组聚合的总个数。
System.out.println("Groups count: " + aggre.getGroups().getGroup().get(0).getCount());
}
}
} else {
System.out.println("NextToken: " + doMetaQueryResult.getNextToken());
}
} catch (OSSException oe) {
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Error Message: " + ce.getMessage());
} finally {
// 关闭OSSClient。
ossClient.shutdown();
}
}
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
from oss2.models import MetaQuery, AggregationsRequest
# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
# 填写Endpoint对应的Region信息,例如cn-hangzhou。注意,v4签名下,必须填写该参数
region = "cn-hangzhou"
# examplebucket填写存储空间名称。
bucket = oss2.Bucket(auth, endpoint, "examplebucket", region=region)
# 查询满足指定条件的Object,并按照指定字段和排序方式列举Object信息。
# 指定查询小于1 MB的文件,且最多返回十个结果,返回结果按升序排列。
do_meta_query_request = MetaQuery(max_results=10, query='{"Field": "Size","Value": "1048576","Operation": "lt"}', sort='Size', order='asc')
result = bucket.do_bucket_meta_query(do_meta_query_request)
# 打印Object名称。
print(result.files[0].file_name)
# 打印Object对应的ETag。
print(result.files[0].etag)
# 打印Object类型。
print(result.files[0].oss_object_type)
# 打印Object存储类型。
print(result.files[0].oss_storage_class)
# 打印Object的64位CRC值。
print(result.files[0].oss_crc64)
# 打印Object的访问权限。
print(result.files[0].object_acl)
package main
import (
"fmt"
"os"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func main() {
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
provider, err := oss.NewEnvironmentVariableCredentialsProvider()
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// 创建OSSClient实例。
// yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
// yourRegion填写Bucket所在地域,以华东1(杭州)为例,填写为cn-hangzhou。其它Region请按实际情况填写。
clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
clientOptions = append(clientOptions, oss.Region("yourRegion"))
// 设置签名版本
clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
client, err := oss.New("yourEndpoint", "", "", clientOptions...)
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// 指定查询大于30字节的文件,且最多返回十个结果,返回结果按升序排列。
query := oss.MetaQuery{
NextToken: "",
MaxResults: 10,
Query: `{"Field": "Size","Value": "30","Operation": "gt"}`,
Sort: "Size",
Order: "asc",
}
// 查询满足指定条件的Object,并按照指定字段和排序方式列举Object信息。
result, err := client.DoMetaQuery("examplebucket", query)
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
fmt.Printf("NextToken:%s\n", result.NextToken)
for _, file := range result.Files {
fmt.Printf("File name: %s\n", file.Filename)
fmt.Printf("size: %d\n", file.Size)
fmt.Printf("File Modified Time:%s\n", file.FileModifiedTime)
fmt.Printf("Oss Object Type:%s\n", file.OssObjectType)
fmt.Printf("Oss Storage Class:%s\n", file.OssStorageClass)
fmt.Printf("Object ACL:%s\n", file.ObjectACL)
fmt.Printf("ETag:%s\n", file.ETag)
fmt.Printf("Oss CRC64:%s\n", file.OssCRC64)
fmt.Printf("Oss Tagging Count:%d\n", file.OssTaggingCount)
for _, tagging := range file.OssTagging {
fmt.Printf("Oss Tagging Key:%s\n", tagging.Key)
fmt.Printf("Oss Tagging Value:%s\n", tagging.Value)
}
for _, userMeta := range file.OssUserMeta {
fmt.Printf("Oss User Meta Key:%s\n", userMeta.Key)
fmt.Printf("Oss User Meta Key Value:%s\n", userMeta.Value)
}
}
}
使用REST API
如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见DoMetaQuery。
检索条件及输出设置
检索条件
以下是完整的检索条件,您可以根据需要进行单独或组合设置。
OSS元数据检索条件
检索条件 | 说明 |
存储类型 | 默认选中OSS支持的标准、低频访问、归档、冷归档和深度冷归档多种存储类型。您可以按需选择希望在查询结果中显示的Object存储类型。 |
读写权限 | 默认选中OSS支持的四种读写权限ACL,即继承Bucket、私有、公共读以及公共读写。您可以按需选择希望在查询结果中显示的Object读写权限。 |
文件名 | 支持模糊匹配和等于。如果您希望在查询结果中显示某个文件名,例如exampleobject.txt。您可以通过以下两种方式匹配目标文件:
|
上传类型 | 默认选中OSS支持的四种Object类型,您可以按需选择希望在查询结果中显示的Object类型。Object类型说明如下:
|
最后修改时间 | 指定Object被最后修改的起始日期和结束日期,时间精确到秒。 |
文件大小 | 支持等于、大于、大于等于、小于和小于等于五种筛选条件,文件大小单位为KB。 |
对象版本 | 仅支持查询当前版本Object。 |
对象Etag及标签检索条件
如需根据对象Etag及标签进行过滤查找,可输入您希望在查询结果中显示的Object对应的ETag或标签信息。
ETag仅支持精确匹配。ETag必须带引号,示例值为"5B3C1A2E0563E1B002CC607C6689"。可输入多个ETag,每行一个。
以键值对(Key-Value)的形式指定对象标签。对象标签的Key和Value均区分大小写。关于标签规则的更多信息,请参见对象标签。
结果输出设置
您可对输出结果进行排序和简单统计。
对象排序方式:支持根据最后修改时间、文件名和文件大小进行升序、降序及默认排序。您可以按需选择并排序检索结果,便于快速找到所需文件。
数据聚合:支持多种输出类型,您可以对检索结果进行去重统计、分组计数、最大值、最小值、平均值和求和等计算,便于高效分析和管理数据。
常见问题
Bucket内文件数量达到上亿级别时,为什么很长时间都没有成功建立数据索引?
1秒内大约可以为600个文件建立索引。您可以结合Bucket内的文件数量,预估建立索引所需时间。
相关文档
标量检索支持多项过滤条件,例如文件最后修改时间、存储类型、读写权限、文件大小等。如果您希望从OSS Bucket的海量Object中筛选出指定时间范围内的Object,请参见如何筛选OSS指定时间范围内的文件?。