gpt4 book ai didi

.NET CosmosDB NoSQL 查询来匹配对象模型

转载 作者:行者123 更新时间:2023-12-03 06:19:57 28 4
gpt4 key购买 nike

我是 noSQL 新手,并且很难理解调用时实际传递给 T 的构造函数的数据

GetItemQueryIterator<T>(query).

我发现的大多数示例都使用“SELECT * FROM mytable”,查询中使用的对象模型是 myTable 数据方案的完整表示,例如包括所有字段。

但是如果我只想在特定查询中从大表中选择几个字段怎么办?我是否需要拥有与不同查询一样多的数据模型类型?

更准确地说,假设我的容器中有类似于下面的文档。我只对 Body 嵌套 JSON 数据感兴趣,其余所有数据实际上是在将数据提供给 CosmosDB 时由 Azure IoTHub 推送到那里的:

    {
"id": "fa14e6f9-b340-4b86-b7b2-46c58318bce5",
"partitionKey": "VK_THC_Outside",
"Properties": {},
"SystemProperties": {
"iothub-connection-device-id": "VK_THC_Outside",
"iothub-connection-auth-method": "{\"scope\":\"device\",\"type\":\"sas\",\"issuer\":\"iothub\",\"acceptingIpFilterRule\":null}",
"iothub-connection-auth-generation-id": "638151591628992733",
"iothub-content-type": "application/json;charset=utf-8",
"iothub-enqueuedtime": "2023-04-08T19:10:50.932Z",
"iothub-message-source": "Telemetry"
},
"iothub-name": "lackoiothub",
"Body": {
"Temp": "3.30",
"Hum": "91.30",
"SBattery": "3532.00",
"GBattery": "4466",
"RSSI": "-48",
"Version": "4",
"TimeStamp": "2023-04-08T19:10:37Z"
}
},

现在我不想对整个文档进行建模或查询,只想使用如下查询来建模或查询其中的一部分:

   var query = new QueryDefinition(
"SELECT i.Body.Temp, i.Body.Hum, i.Body.SBattery, i.Body.GBattery, i.Body.TimeStamp " +
"FROM iothub i " +
"WHERE i.partitionKey = \"VK_THC_Outside\" and i.Body.TimeStamp >= @minDate " +
"ORDER BY i.Body.TimeStamp desc"
).WithParameter("@minDate", DateTime.Today);

我假设我会将字段重新调整为 Temp、Hum、SBattery、GBattery 和 TimeStamp,因此我创建了一个模型对象:

public class SensorData
{
public string temp { get; set; } = "0";
public string hum { get; set; } = "0";
public string sbatt { get; set; } = "0";
public string gbatt { get; set; } = "0";
public DateTime time { get; set; }

public SensorData(string temp, string hum, string sbatt, string gbatt, string time)
{
Debug.WriteLine($"Sensordata.ctor() : temp: {temp} hum: {hum} sbatt: {sbatt} gbatt: {gbatt} time: {time}");
try
{
this.temp = temp;
this.hum = hum;
this.sbatt = sbatt;
this.gbatt = gbatt;
this.time = DateTime.Parse(time);
}
catch (Exception ex)
{
Debug.WriteLine($"Sensordata.ctor() : Exception : {ex.GetType().Name} {ex.Message}");
this.time = DateTime.Now;
}
}
}

将这些放在一起,我有以下代码:

      var query = new QueryDefinition(
"SELECT i.Body.Temp, i.Body.Hum, i.Body.SBattery, i.Body.GBattery, i.Body.TimeStamp " +
"FROM iothub i " +
"WHERE i.partitionKey = \"VK_THC_Outside\" and i.Body.TimeStamp >= @minDate " +
"ORDER BY i.Body.TimeStamp desc"
).WithParameter("@minDate", DateTime.Today);


using FeedIterator<SensorData> feed = container.GetItemQueryIterator<SensorData>(query);

while (feed.HasMoreResults)
{
var sData = await feed.ReadNextAsync();
sData.ForEach(d => _sensorsData.Add(d));
}

事实证明这不起作用,我没有收到传递给 SensorData 构造函数的数据或收到奇怪的数据。感谢调试消息,我可以看到数据未按预期传递。没有为参数 sbatt、gbatt 和时间的 SensorData 构造函数传递任何数据:

Sensordata.ctor() : Exception : ArgumentNullException Value cannot be null. (Parameter 's')
Sensordata.ctor() : temp: 3.50 hum: 91.30 sbatt: gbatt: time:
Exception thrown: 'System.ArgumentNullException' in System.Private.CoreLib.dll
Sensordata.ctor() : Exception : ArgumentNullException Value cannot be null. (Parameter 's')
Sensordata.ctor() : temp: 3.50 hum: 91.20 sbatt: gbatt: time:
Exception thrown: 'System.ArgumentNullException' in System.Private.CoreLib.dll
Sensordata.ctor() : Exception : ArgumentNullException Value cannot be null. (Parameter 's')
Sensordata.ctor() : temp: 3.60 hum: 91.20 sbatt: gbatt: time:
Exception thrown: 'System.ArgumentNullException' in System.Private.CoreLib.dll
Sensordata.ctor() : Exception : ArgumentNullException Value cannot be null. (Parameter 's')
Sensordata.ctor() : temp: 3.60 hum: 91.10 sbatt: gbatt: time:
Exception thrown: 'System.ArgumentNullException' in System.Private.CoreLib.dll
Sensordata.ctor() : Exception : ArgumentNullException Value cannot be null. (Parameter 's')

因此,我找到了另一种方法来首先避免反序列化并检查查询实际返回的数据。为此,我用 GetItemQueryStreamIterator 替换了通用 GetItemQueryIterator,并使用以下代码进行相同的查询:

using FeedIterator feed = container.GetItemQueryStreamIterator(query);

while (feed.HasMoreResults)
{
var response = await feed.ReadNextAsync();
using (StreamReader sr = new StreamReader(response.Content))
using (JsonTextReader jtr = new JsonTextReader(sr))
{
JObject result = JObject.Load(jtr);
}

检查上面循环中变量“result”的值,我现在可以看到查询结果实际上符合预期:

enter image description here

有人可以指出我正确的方向吗

container.GetItemQueryIterator<SensorData>(query)

没有按预期工作?

最佳答案

您需要尊重属性的大小写或使用装饰器来分配哪个 Json 属性与哪个类属性匹配。

第一个是最简单的:

public class SensorData
{
public string Temp { get; set; } = "0";
public string Hum { get; set; } = "0";
public string SBattery { get; set; } = "0";
public string GBattery { get; set; } = "0";
public DateTime TimeStamp { get; set; }
}

您还可以使用JObject:

container.GetItemQueryIterator<JObject>(query)

并使用 JObject 访问器(例如 item["Hum"])来获取 Hum 属性值。

关于.NET CosmosDB NoSQL 查询来匹配对象模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75967361/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com