使用标量检索基于元数据属性查询OSS中的文件

标量检索是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为广州地域

  1. 登录OSS管理控制台

  2. 单击Bucket 列表,然后单击目标Bucket名称。

  3. 在左侧导航栏, 选择文件管理 > 数据索引

  4. 数据索引页面,单击立即开启

  5. 选择标量检索,单击确认开启

    说明

    开启标量检索需要等待一定的时间,具体等待时长取决于Bucket中Object的数量。

  6. 按以下说明设置OSS元数据检索条件,其他参数保留默认设置。

    • 最后修改时间设置为2024年9月11日0:00至2024年9月12日0:00。

    • 文件大小设置为小于500KB。

    image

  7. 设置输出方式

    • 对象排序方式选择按照文件大小升序排列。

    • 数据聚合选择按照文件大小最大值聚合输出

    image

  8. 单击立即查询。符合检索条件的所有文件共2个,如下图所示,文件最大为434KB。

    image

如需了解完整的检索条件和输出设置,请参见检索条件及输出设置

Bucket为杭州、上海、青岛、北京、张家口、深圳、成都、中国香港、新加坡、雅加达、法兰克福、弗吉尼亚、硅谷、伦敦地域

  1. 登录OSS管理控制台

  2. 单击Bucket 列表,然后单击目标Bucket名称。

  3. 在左侧导航栏, 选择文件管理 > 数据索引

  4. 开启元数据管理

    说明

    开启元数据管理需要等待一定的时间,具体等待时长取决于Bucket中Object的数量。

  1. 按以下说明设置对象基础过滤条件,其他参数保留默认设置。

    • 最后修改时间设置为2024年9月11日0:00至2024年9月12日0:00。

    • 文件大小设置为小于500KB。

    image

  2. 展开更多过滤条件

    • 对象排序方式选择按照文件大小升序排列。

    • 数据聚合选择按照文件大小最大值聚合输出。

    image

  3. 单击查询。符合检索条件的所有文件共2个,如下图所示,文件最大为434KB。

    image

    如需了解完整的检索条件和输出设置,请参见检索条件及输出设置

使用阿里云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。您可以通过以下两种方式匹配目标文件:

  • 选择等于,然后输入完整的文件名称exampleobject.txt

  • 选择模糊匹配,然后输入文件前缀或者后缀,例如example或者.txt

    重要

    模糊匹配可命中Object名称的任意字符,例如输入test,则查询结果中将显示localfolder/test/.example.jpglocalfolder/test.jpg等。

上传类型

默认选中OSS支持的四种Object类型,您可以按需选择希望在查询结果中显示的Object类型。Object类型说明如下:

  • Normal:通过简单上传方式生成的Object。

  • Multipart:通过分片上传方式生成的Object。

  • Appendable:通过追加上传方式生成的Object。

  • Symlink:为快速访问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指定时间范围内的文件?。