我无法从 CosmosDb 文档中检索对象列表
I can not retrieve a list of objects from CosmosDb document
我使用 ComsosDb .NET SDK 3 进行 SQL 查询时出错。我想从文档中请求对象列表。
这是我存储在 CosmosDb 中的文档(fid 是分区键):
{
"id": "1abc",
"fid": "test",
"docType": "Peeps",
"People": [
{
"Name": "Bill",
"Age": 99
},
{
"Name": "Marion",
"Age": 98
},
{
"Name": "Seb",
"Age": 97
}
],
"_rid": "mo53AJczKUuL9gMAAAAAAA==",
"_self": "dbs/mo53AA==/colls/mo53AJczKUs=/docs/mo53AJczKUuL9gMAAAAAAA==/",
"_etag": "\"9001cbc7-0000-1100-0000-60c9d58d0000\"",
"_attachments": "attachments/",
"_ts": 1623840141
}
我的结果显示项目数为 1,属性设置为默认值 - 姓名为空,年龄为 0。
我期待 3 人的 IEnumerable。这是代码:
class MyPeople
{
public IEnumerable<Person> People { get; set; }
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
[Fact]
public async Task CosmosPeopleTest_ReturnsThreePeople()
{
var config = GetConFig();
var cosmosClientV2 = new CosmosClient(config["Cosmos:ConnectionString"]);
var container = cosmosClientV2.GetContainer(config["Cosmos:DbName"], config["Cosmos:Collectionname"]);
var sql = "SELECT c.People FROM c WHERE c.docType = 'Peeps'";
QueryDefinition queryDefinition = new QueryDefinition(sql);
var results = new List<Person>();
FeedIterator<Person> q = container.GetItemQueryIterator<Person>(queryDefinition, null, new QueryRequestOptions { PartitionKey = new PartitionKey("test") });
while (q.HasMoreResults)
{
var x = await q.ReadNextAsync();
results.AddRange(x.ToList());
}
Assert.Equal(3, results.Count);
}
如果我将查询更改为
sql = "SELECT c.People FROM c JOIN d IN c.People";
我有三个 Person 都具有默认属性 Name 和 Age。
你的类型有问题。 SELECT c.People
return 这种形式的对象:
{
People: [
...
]
}
当您使用此代码进行迭代时
FeedIterator<Person> q = container.GetItemQueryIterator<Person>(queryDefinition, null, new QueryRequestOptions { PartitionKey = new PartitionKey("test") });
CosmosDB 尝试将每个结果对象(如上所述)“转换”为 Person
class。但它为此使用反射。因此它创建了一个 Person
对象但没有找到任何字段来填充其属性 - 它不会失败,但会创建所有属性都使用默认值初始化的空对象。
所以要解决它你需要使用 MyPeople
而不是 Person
:
FeedIterator<MyPeople> q = container.GetItemQueryIterator<MyPeople>(queryDefinition, null, new QueryRequestOptions { PartitionKey = new PartitionKey("test") });
由于 MyPeople
是 returned 对象的正确形式,它将能够读取 CosmosDB return 的对象并使用它们。
完整的工作代码:
var config = GetConFig();
var cosmosClientV2 = new CosmosClient(config["Cosmos:ConnectionString"]);
var container = cosmosClientV2.GetContainer(config["Cosmos:DbName"], config["Cosmos:Collectionname"]);
var sql = "SELECT c.People FROM c WHERE c.docType = 'Peeps'";
QueryDefinition queryDefinition = new QueryDefinition(sql);
var results = new List<Person>();
FeedIterator<MyPeople> q = container.GetItemQueryIterator<MyPeople>(queryDefinition, null, new QueryRequestOptions { PartitionKey = new PartitionKey("test") });
while (q.HasMoreResults)
{
var x = await q.ReadNextAsync();
var myPeopleRes = x.Resource;
foreach (var people in myPeopleRes)
{
results.AddRange(people.People);
}
}
Assert.Equal(3, results.Count);
我使用 ComsosDb .NET SDK 3 进行 SQL 查询时出错。我想从文档中请求对象列表。 这是我存储在 CosmosDb 中的文档(fid 是分区键):
{
"id": "1abc",
"fid": "test",
"docType": "Peeps",
"People": [
{
"Name": "Bill",
"Age": 99
},
{
"Name": "Marion",
"Age": 98
},
{
"Name": "Seb",
"Age": 97
}
],
"_rid": "mo53AJczKUuL9gMAAAAAAA==",
"_self": "dbs/mo53AA==/colls/mo53AJczKUs=/docs/mo53AJczKUuL9gMAAAAAAA==/",
"_etag": "\"9001cbc7-0000-1100-0000-60c9d58d0000\"",
"_attachments": "attachments/",
"_ts": 1623840141
}
我的结果显示项目数为 1,属性设置为默认值 - 姓名为空,年龄为 0。 我期待 3 人的 IEnumerable。这是代码:
class MyPeople
{
public IEnumerable<Person> People { get; set; }
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
[Fact]
public async Task CosmosPeopleTest_ReturnsThreePeople()
{
var config = GetConFig();
var cosmosClientV2 = new CosmosClient(config["Cosmos:ConnectionString"]);
var container = cosmosClientV2.GetContainer(config["Cosmos:DbName"], config["Cosmos:Collectionname"]);
var sql = "SELECT c.People FROM c WHERE c.docType = 'Peeps'";
QueryDefinition queryDefinition = new QueryDefinition(sql);
var results = new List<Person>();
FeedIterator<Person> q = container.GetItemQueryIterator<Person>(queryDefinition, null, new QueryRequestOptions { PartitionKey = new PartitionKey("test") });
while (q.HasMoreResults)
{
var x = await q.ReadNextAsync();
results.AddRange(x.ToList());
}
Assert.Equal(3, results.Count);
}
如果我将查询更改为
sql = "SELECT c.People FROM c JOIN d IN c.People";
我有三个 Person 都具有默认属性 Name 和 Age。
你的类型有问题。 SELECT c.People
return 这种形式的对象:
{
People: [
...
]
}
当您使用此代码进行迭代时
FeedIterator<Person> q = container.GetItemQueryIterator<Person>(queryDefinition, null, new QueryRequestOptions { PartitionKey = new PartitionKey("test") });
CosmosDB 尝试将每个结果对象(如上所述)“转换”为 Person
class。但它为此使用反射。因此它创建了一个 Person
对象但没有找到任何字段来填充其属性 - 它不会失败,但会创建所有属性都使用默认值初始化的空对象。
所以要解决它你需要使用 MyPeople
而不是 Person
:
FeedIterator<MyPeople> q = container.GetItemQueryIterator<MyPeople>(queryDefinition, null, new QueryRequestOptions { PartitionKey = new PartitionKey("test") });
由于 MyPeople
是 returned 对象的正确形式,它将能够读取 CosmosDB return 的对象并使用它们。
完整的工作代码:
var config = GetConFig();
var cosmosClientV2 = new CosmosClient(config["Cosmos:ConnectionString"]);
var container = cosmosClientV2.GetContainer(config["Cosmos:DbName"], config["Cosmos:Collectionname"]);
var sql = "SELECT c.People FROM c WHERE c.docType = 'Peeps'";
QueryDefinition queryDefinition = new QueryDefinition(sql);
var results = new List<Person>();
FeedIterator<MyPeople> q = container.GetItemQueryIterator<MyPeople>(queryDefinition, null, new QueryRequestOptions { PartitionKey = new PartitionKey("test") });
while (q.HasMoreResults)
{
var x = await q.ReadNextAsync();
var myPeopleRes = x.Resource;
foreach (var people in myPeopleRes)
{
results.AddRange(people.People);
}
}
Assert.Equal(3, results.Count);