【问题标题】:Querying complex nested object in cosmosdb using sql Api使用 sql Api 在 cosmosdb 中查询复杂的嵌套对象
【发布时间】:2020-08-17 13:14:57
【问题描述】:

如何使用 sql api 从 comosdb 的复杂嵌套对象(使用动态键)中仅查询 Itemcount > 10 的用户? UDF 不是首选。

类似的,

Select c.username from c where c.Data[*].Order.ItemCount > 10;

 {
  {
    "Username": "User1",
    "Data": {
        "RandomGUID123": {
                "Order": {               
                    "Item": "ItemName123",
                    "ItemCount" : "40"
                },
                "ShipmentNumber": "7657575"
            },
        "RandomGUID976": {
                "Order": {               
                    "Item": "ItemName7686"
                    "ItemCount" : "7"
                },
                "ShipmentNumber": "876876"
             }
          }
  },     
  {
    "Username": "User2",
    "Data": {
        "RandomGUID654": {
            "Order": {               
                "Item": "ItemName654",
                "ItemCount" : "9"
            },
            "ShipmentNumber": "7612575"
        },
        "RandomGUID908": {
            "Order": {               
                "Item": "ItemName545"
                "ItemCount" : "6"
            },
            "ShipmentNumber": "6454"
        }
      }
  }
}

【问题讨论】:

  • 除了以下建议还有其他方法吗?没有 UDF 并且没有改造上述数据结构。

标签: linq azure-cosmosdb azure-cosmosdb-sqlapi


【解决方案1】:

我不确定如何处理未知键,但如果您愿意将键建模为一个值(我认为更简单、更简洁),您可以:

{
    "Username": "User1",
    "Data": [
        {
            "Id": "RandomGUID123",
            "Order": {
                "Item": "ItemName123",
                "ItemCount": 40
            },
            "ShipmentNumber": "7657575"
        },
        {
            "Id": "RandomGUID976",
            "Order": {
                "Item": "ItemName7686",
                "ItemCount": 7
            },
            "ShipmentNumber": "876876"
        }
    ]
}

使用如下查询:

SELECT DISTINCT VALUE(c.Username) 
FROM c
JOIN (SELECT VALUE d from d IN c.Data where d["Order"].ItemCount > 10)

结果:

[
    "User1"
]

“订单”是保留关键字,需要括号语法来引用。

【讨论】:

  • 重塑不是一种选择,因为真正的“Id”字段有一些保留的特殊字符,例如“/RandomIdGuid”,cosmos db 不会接受作为“Key”字段。
  • 这不是存储为属性值的另一个原因吗?
  • 我错了,但您对上述说法是正确的。仍然改造不是一种选择,它已经退出模型超过几年了,许多许多逻辑都围绕着这个模型。
  • 折衷办法是在文档上存储一个附加属性,即您要查询的计算结果,例如 UserItemCount。然后在执行写入或维护作业的任何逻辑中保持该值的更新。这不会影响任何现有的逻辑。
  • LINQ 是 C# 构造,而不是 Cosmos 构造。 LINQ 可以表达比实际转换为 Cosmos 查询更多的可能性,这正是 SDK 所做的。除非您可以直接编写查询文本,否则不要假设您的 LINQ 查询是有意义的。
【解决方案2】:

正如诺亚所回答的,将键建模为值是一种实现方式。

此外,还有另一种方法可以在不更改文档架构的情况下实现。像这样创建 UDF:

function getResult(data){
  for(var key in data){
    const itemCount = data[key].Order.ItemCount;
    if (parseFloat(itemCount).toString() != "NaN" && parseFloat(itemCount) > 10 ) {
    return true;
  }
  }
  return false;
}

然后运行这条sql:

SELECT c.Username FROM c where udf.getResult(c.Data)

结果:

[
    {
        "Username": "User1"
    }
]

【讨论】:

    猜你喜欢
    • 2020-03-24
    • 2018-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    • 1970-01-01
    相关资源
    最近更新 更多