如何通过 rusoto / rust 使用 select_object_content?

How to use select_object_content via rusoto / rust?

以下代码尝试 select 存储在 S3 上的文件中的一些数据:

  let client = S3Client::new(Region::default());
  let source = ... object providing bucket and key ...;

  let r = SelectObjectContentRequest {
      bucket: source.bucket,
      key: source.key,
      expression: "select id from S3Object[*].id".to_string(),
      expression_type: "SQL".to_string(),
      input_serialization: InputSerialization {
          json: Some(JSONInput { type_: Some("LINES".to_string()) }),
          ..Default::default()
      },
      output_serialization: OutputSerialization {
          json: Some(JSONOutput { record_delimiter: Some("\n".to_string()) }),
          ..Default::default()
      },
      ..Default::default()
  };

它会导致以下错误:

The specified method is not allowed against this resource.POST

该示例是工作 Python/boto3 示例的 1:1 端口,所以我很确定它应该可以工作。我发现这个 issue,它已经几个月大了,我不清楚它的状态。我如何让它与 Rust 一起工作?

不幸的是,s3 select 仍然无法在最新的 rusoto_s3-0.40.0 上运行。您链接的 issue 有所有答案。问题是双重的。

首先,现在 s3 select 请求 rusoto 发出了一个伪造的查询字符串。它应该是 /ObjectName?select&select-type=2,但 rusoto 将其编码为 /bjectName?select%26select-type=2。那是你看到的错误。

为了验证,运行 你的项目是这样的:

$ RUST_LOG=rusoto,hyper=debug cargo run

您将看到来自 rusotohyper 的日志。果然它发出了一个不正确的 URI。甚至可以深入研究 the code responsible:

let mut params = Params::new();
params.put("select&select-type", "2");
request.set_params(params);

应该是:

let mut params = Params::new();
params.put("select-type", "2");
params.put("select", "");
request.set_params(params);

虽然修复看起来微不足道,但请记住这些是从 AWS botocore 服务清单生成的胶水代码,而不是手动编码。合并修复程序并不是那么简单。

其次,更大的问题。 AWS s3 select 响应使用 customized binary formatrusoto 还没有反序列化器。