我一直在使用
Google.Cloud.BigQuery.V2
nuget 包,但似乎无法找到任何创建用于表创建/行插入的不平凡(我的意思是非平面)模式的具体示例。
我们以这个对象为例:
public class DataEntry
{
public string Id { get; set; }
public string Name { get; set; }
public DateTime Created { get; set; }
public Dictionary<string, string> Items { get; set; }
}
Items
字典可能为空或包含许多条目。
通过阅读文档,我希望
.Items
能够映射为 ARRAY
的 STRUCT<string, string>
,但我似乎无法弄清楚如何在代码中实际映射这种对象。
谁能给我举个例子吗?
谢谢!
多读一点之后,就会发现,虽然在将
ARRAY
类型的字段添加到 BigQueryDbType.DateTime
时可以在模式中指定 TableSchemaBuilder
,但它不能与 STRUCT
组合来映射字典。 事后看来,其原因相当明显 - STRUCT
本质上就像 System.Object
一样,因为它的属性(字典键)需要提前知道。
简而言之,这永远不会适用于我的场景,因为字典键/值对是动态的并且不会事先知道。
深入研究支持的查询时函数后,我发现了
JSON_EXTRACT
函数,它提供了一条出路。通过将字典扁平化为 json 并使用 BigQueryDbType.String
的基类型存储它,我有办法保存动态数据并在另一端查询它。
有了这些信息,为上面的对象构建模式的代码将如下所示:
// Build our object
var builder = new TableSchemaBuilder();
builder.Add("Id", BigQueryDbType.String, BigQueryFieldMode.Required);
builder.Add("Name", BigQueryDbType.String, BigQueryFieldMode.Required);
builder.Add("Inserted", BigQueryDbType.DateTime, BigQueryFieldMode.Required);
// ...
// ... Rest of fields
// ...
builder.Add("Items", BigQueryDbType.String, BigQueryFieldMode.Nullable);
// Build our schema
var schema = builder.Build();
假设
Items
值为 {"KeyOne":"ItemOne", "KeyTwo":"ItemTwo"}
,梳理出字典中第一个值的查询将如下所示:
SELECT JSON_EXTRACT(Items, "$.KeyOne") AS KeyOne FROM `mytable` LIMIT 1000
希望这会节省其他人一些时间:)
我可以通过声明以下内容来做到这一点:
var dataSchema = new TableSchemaBuilder()
{
{ "Key", BigQueryDbType.String, BigQueryFieldMode.Required },
{ "Value", BigQueryDbType.String, BigQueryFieldMode.Required },
}.Build();
然后在我的表架构中使用以下行:
var tableSchema = new TableSchemaBuilder()
{
...
{ "Data", dataSchema, BigQueryFieldMode.Repeated},
}.Build();
插入项目时,我有一个列表
var row = new BigQueryInsertRow() {...};
var data = new List<BigQueryInsertRow>();
foreach (var keyValuePair in items) {
var dataRow = new BigQueryInsertRow { { "Key", keyValuePair.Key }, { "Value", keyValuePair.Value } };
data.Add(dataRow);
}
row["Data"] = data;
这是 Google.Cloud.BigQuery.V2 版本 3.10.0。