按嵌套集合过滤计数排序

Posted

技术标签:

【中文标题】按嵌套集合过滤计数排序【英文标题】:Order by nested collection filtered count 【发布时间】:2022-01-10 17:25:46 【问题描述】:

我正在尝试,但不知道如何在 OData 中执行此操作。

我将使用公共 OData API(来自 Microsoft)进行演示来解释我的意思,无需授权

https://services.odata.org/TripPinRESTierService/

所以我们在那里有People

https://services.odata.org/TripPinRESTierService/People

这些PeopleTrips

https://services.odata.org/TripPinRESTierService/People?$expand=Trips

如果我想通过Name 过滤Trips,这很容易

https://services.odata.org/TripPinRESTierService/People?$expand=Trips($filter=Name eq 'Trip in Beijing')

如果我想按Trip 计数订购People,也很简单

https://services.odata.org/TripPinRESTierService/People?$expand=Trips($count=true)&$orderby=Trips/$count desc

但我无法通过过滤的行程次数进行排序(例如$expand=Trips($filter=Name eq 'Trip in Beijing')

https://services.odata.org/TripPinRESTierService/People?$expand=Trips($count=true;$filter=Name eq 'Trip in Beijing')&$orderby=Trips/$count desc

&$orderby=Trips($filter=Name eq 'Trip in Beijing')/$count desc&$orderby=Trips/$count($filter=Name eq 'Trip in Beijing') desc 之类的东西不起作用(导致服务器错误 "Could not find a property named 'Name' on type 'Trippin.Person'.")。

此 URL 的版本以查看所需的最少数据

https://services.odata.org/TripPinRESTierService/People?$expand=Trips($top=0;$count=true;$filter=Name eq 'Trip in Beijing')&$orderby=Trips/$count desc&$select=Trips

更新:我在我的项目中使用Microsoft.AspNetCore.OData 7.5.7 版本,它依赖于Microsoft.OData.Core 7.7.3 版本(未明确安装)。如果微软将在其 API 中升级 OData 版本,它可能也会正常工作。

【问题讨论】:

您好,请问您在查询时能提供从服务器得到的错误信息吗? @Max 哪一个?请注意,您可以在浏览器或 Postman 中运行所有列出的查询并进行试验。 【参考方案1】:

更新这仅支持基于 this pr 的 Microsoft.OData.Core 版本 >= 7.9.4。


您应该能够在您的 $orderby 中重复与您在 $expand 中相同的过滤条件,以获得您正在寻找的内容。

/odata/People?$expand=Trips($count=true;$filter=Name eq 'Paris')&$orderby=Trips/$count($filter=Name eq 'Paris') desc

"@odata.context": "https://localhost:5001/odata/$metadata#People(Trips())",
"value": [
    
        "Id": "d31713ca-236b-470f-bb9e-f5bd6fac3d8e",
        "Name": "Aaron",
        "Trips@odata.count": 2,
        "Trips": [
            
                "Id": "741656bf-f5e6-4f18-855f-ca1b3c0eb478",
                "Name": "Paris"
            ,
            
                "Id": "741656bf-f5e6-4f18-855f-ca1b3c0eb478",
                "Name": "Paris"
            
        ]
    ,
    
        "Id": "34c0ac10-1c0d-4a29-89ad-386a3fea893b",
        "Name": "Bob",
        "Trips@odata.count": 1,
        "Trips": [
            
                "Id": "1b35a96d-ca98-438a-b63c-1478ae0661cb",
                "Name": "Paris"
            
        ]
    ,
    
        "Id": "192dd197-6f25-4842-bb9f-207b5df221c2",
        "Name": "Jeff",
        "Trips@odata.count": 0,
        "Trips": []
    
  ]

为了比较,这里是没有 $filter 的相同数据集。

/odata/People?$expand=Trips($count=true)&$orderby=Trips/$count desc

"@odata.context": "https://localhost:5001/odata/$metadata#People(Trips())",
"value": [
    
        "Id": "192dd197-6f25-4842-bb9f-207b5df221c2",
        "Name": "Jeff",
        "Trips@odata.count": 3,
        "Trips": [
            
                "Id": "4537521c-27a6-4fa4-8bb5-fd94937abd56",
                "Name": "Cleveland"
            ,
            
                "Id": "40431cba-0d8f-470a-9647-bdd99009737a",
                "Name": "Cleveland"
            ,
            
                "Id": "1269c3e3-b5ff-4a73-8201-5388d00ea744",
                "Name": "Cleveland"
            
        ]
    ,
    
        "Id": "d31713ca-236b-470f-bb9e-f5bd6fac3d8e",
        "Name": "Aaron",
        "Trips@odata.count": 2,
        "Trips": [
            
                "Id": "741656bf-f5e6-4f18-855f-ca1b3c0eb478",
                "Name": "Paris"
            ,
            
                "Id": "741656bf-f5e6-4f18-855f-ca1b3c0eb478",
                "Name": "Paris"
            
        ]
    ,
    
        "Id": "34c0ac10-1c0d-4a29-89ad-386a3fea893b",
        "Name": "Bob",
        "Trips@odata.count": 1,
        "Trips": [
            
                "Id": "1b35a96d-ca98-438a-b63c-1478ae0661cb",
                "Name": "Paris"
            
        ]
    
  ]

【讨论】:

我明白了。在您的示例中对 api 进行相同的尝试会给我相同的结果。在您的最终实施中,您是否使用特定版本的 OData?我能够使用 OData 8.0.4 使用本地 .NET 5 Web API 可靠地重现我的答案中的行为。我很乐意分享我的源代码。 我发现了这个 pr,这让我觉得这可能只在更新的版本中得到支持。 github.com/OData/odata.net/pull/2051/files 如果你想进一步深入了解,这里是我的仓库github.com/tyharbert/ODataApiSandbox 太好了,我能够对其进行测试并设法升级我的代码。 NuGet 包Microsoft.AspNetCore.OData 8.0+ 版本有大量的重大变化,我什至可以说它完全重新设计了 API。所以我还没有计划升级它,因为它需要付出巨大的努力来升级。我可以通过将Microsoft.AspNetCore.OData 从版本 7.5.7 升级到目前最新的 7.x 版本 7.5.12 来修复它。这取决于包含此修复程序的 Microsoft.OData.Core 版本 7.9.0。 所以解决方案是选项 1:使用 7.5.12 版的Microsoft.AspNetCore.OData(或更高版本,如果将发布),它将隐式使用Microsoft.OData.Core 7.9.0 版(或更高版本)或选项 2:显式安装 Microsoft.OData.Core 版本 7.9.0+。

以上是关于按嵌套集合过滤计数排序的主要内容,如果未能解决你的问题,请参考以下文章

根据对多关系中相关对象的计数对获取请求进行排序

ArrayList 集合统计数的个数

数据框:如何在 Scala 中分组/计数然后按计数排序

计数排序是个啥?

根据重复计数对集合进行区分和排序

Cassandra 按计数排序结果