【问题标题】:Select distinct values with odata使用 odata 选择不同的值
【发布时间】:2010-10-01 12:21:33
【问题描述】:

我正在尝试创建对 odata webservice 的调用,该调用将仅选择某些属性的不同值。有没有很好的例子说明如何做到这一点?

【问题讨论】:

标签: odata


【解决方案1】:

目前 OData 协议不支持 distinct 运算符,或任何其他有助于此类查询的运算符(假设您正在寻找某个实体上原始属性的不同值)。 您应该能够通过在服务器上实现服务操作来解决此问题,该服务操作对通常具有该功能的底层提供程序执行此类查询。然后客户端可以改为调用该服务操作。

【讨论】:

  • 在 2014 年 2 月 24 日使用 Odata 4.0 时仍然如此
  • 2017 年依然如此:'(
  • 2018 年依然如此:'(
  • 2021 年依然如此:'(
  • 2022 年依然如此:'(
【解决方案2】:

注意:我知道这是旧的,但仍然出现在搜索响应中。这个问题现在有一个很好的解决方案。

在 OData v4 中,支持 $apply,其中,$apply 可用于从结果集中返回一组不同的字段。

见相关讨论:Applying Distinct to ODataQuery

来自OData v4 spec
查询选项$apply 采用一系列集合转换,由正斜杠分隔以表示它们是连续应用的,例如每个变换的结果是下一个变换的输入 $apply 是一个函数,需要

tl;dr;
基本上,如果我有一个包含许多字段的表,但我只想返回多个特定字段的不同记录,那么第一步是识别不同的列,我们称它们为 NameId
只需使用 $apply 函数即可获得一个不同的结果集,其中仅包含 Names 和 Id 列,语法如下:

http://url.to/tableresource?$apply=groupby((Name,Id))

让我们举个例子,TuberInspections 有 1000 行,但只有几个承包商,我想在下拉列表中显示承包商的名称以用于过滤查询。

我的不同列是ContractorNameContractorId

GET /odata/TuberInspections?$apply=groupby((ContractorName,ContractorId)) HTTP/1.1
Host: localhost:1230

Response:
    { 
        "@odata.context": "http://localhost:1230/odata/$metadata#TuberInspections(ContractorName,ContractorId)",
        "value": [
            {
                "@odata.id": null,
                "ContractorId": 11534,
                "ContractorName": "Kermit d'Frog"
            },
            {
                "@odata.id": null,
                "ContractorId": 11539,
                "ContractorName": "Carlos Spicy Wiener"
            },
            {
                "@odata.id": null,
                "ContractorId": 16827,
                "ContractorName": "Jen Gelfling"
            }
        ]
    }

如果您的数据结构不够平坦,则 OOTB 对检索简单嵌套结果结构的支持有限。

如果他的数据结构难以使用并且您可以控制 API,那么您应该考虑创建一个自定义函数来返回您想要的特定记录集,这是一个简单的练习,您可以使用许多不同的选项,但是不在此回复的范围内。

此响应针对如何查询现有 OData 服务以获取不同的值,而不是如何修改服务以提供此类信息。

目前仅支持使用以下语法的单个导航路径。上面的查询也可以写成:

GET /odata/TuberInspections?$apply=groupby((Contractor/EntityID,Contractor/Initials))
Host: localhost:1230

Response:
    { 
         "@odata.context": "http://localhost:1230/odata/$metadata#TuberInspections(Contractor(EntityID,Initials))",
         "@odata.count": 3,
         "value": [
             {
                 "@odata.id": null,
                 "Contractor": {
                     "@odata.id": null,
                     "Initials": "KdF",
                     "EntityID": 11534
                 }
             },
             {
                 "@odata.id": null,
                 "Contractor": {
                     "@odata.id": null,
                     "Initials": "SW",
                     "EntityID": 11539
                 }
             },
             {
                 "@odata.id": null,
                 "Contractor": {
                     "@odata.id": null,
                     "Initials": "Jen",
                     "EntityID": 16827
                 }
             }
         ]
    } 

嵌套或堆叠$apply 转换有更高级(复杂)的变体,包括返回与每个不同结果对应的唯一行数的计数。

在组内包含$count 的不同记录在此处进行了记录System Query Option $apply - groupby 并响应OData v4 groupby with $count

GroupBy 支持aggregate extension,所以我们可以在前面的 URL 中使用它,记得给投影的列名取别名

groupby((Contractor/EntityID,Contractor/Initials),aggregate($count as Items))

响应现在包括计数:

       {
            "@odata.id": null,
            "Items": 260,
            "Contractor": {
                "@odata.id": null,
                "Initials": "SW",
                "EntityID": 11539
            }
        },

有关更多信息,请使用 OData-v4 发布具体问题和标签,您将找到所需的所有帮助 :)

【讨论】:

  • 这似乎类似于使用 select a,b group by a,b 来获得应该选择不同的 a,b 的内容。我仍然喜欢不同运算符的概念——我不想实现数据转换服务。
  • 本质上,distinct 和 group by 占用相同的服务器资源并且是相同的计算,只有一种响应类型来覆盖这两种场景是有意义的。问题是如何在规范中定义标准响应。在许多使用不同查询的情况下,如果结构没有改变,那么计算匹配项的数量可能很有用,那么作为 OData 规范的一部分,必须假设每一行都有一个唯一的 id对应的资源,但是因为我们只请求了唯一值,所以没有唯一键。
  • 如果您可以控制服务代码,那么请务必创建一个仅返回您想要的不同记录集的函数 :) 此响应更多地是关于如何查询现有或第 3 方 API对于不同的记录集。我 100% 支持自定义端点,以方便客户端使用。
  • @ChrisSchaller 在倒数第二段中,您提到还能够返回唯一行的计数。你能告诉我那个网址会是什么样子吗?在 odata 文档中找不到它
  • $apply 不在 Dynamics 365 支持的查询选项列表中:docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-17
相关资源
最近更新 更多