ZEXSM / OData.QueryBuilder

OData.QueryBuilder - library for creating complex OData queries (OData version 4.01) based on data models with linq syntax.
MIT License
72 stars 31 forks source link

IODataStringAndCollectionFunction does not support Collection yet #35

Closed ziyike closed 3 years ago

ziyike commented 3 years ago

The use case is, there is a List<string> property, say "labels", then the filter string would be like "contains(labels, "lb1") or contains(labels, "lb2") or ...".

ZEXSM commented 3 years ago

Hey. If I understood correctly, then there is not enough opportunity

contains http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_contains with OrderedCollection support

I will try to add it soon.

ZEXSM commented 3 years ago

I initially misunderstood. The problem is solved like this

var  list = new List<string>
{
    "l",
    "b",
    "1"
};
var labels string.Join("", list );
...
contains(labels, "lb1")
...

According to the spec http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_contains, contains does not accept a list of strings

ziyike commented 3 years ago

Thanks! I noticed that the contains(labels, "lb1") can be achieved by replacing the Collection property with a simple String, however, this is a bit counter-intuitive. And I did misunderstand the Collection as any ICollection, sorry about that. Then maybe support for IOrderedCollection could be implemented?

ZEXSM commented 3 years ago

Hey. I was mistaken when I suggested this option, it is in principle not working.

var  list = new List<string>
{
    "l",
    "b",
    "1"
};
var labels string.Join("", list );
...
contains(labels, "lb1")
...

Now I looked at the problem differently and I can suggest the following

var uri = _odataQueryBuilderDefault
    .For<ODataTypeEntity>(s => s.ODataType)
    .ByList()
    .Filter((s, f, o) => o.Any(s.Labels, label => label == "lb1" || label == "lb2"))
    .ToUri();
uri.OriginalString.Should().Be("http://mock/odata/ODataType?$filter=Labels/any(label:label eq 'lb1' or label eq 'lb2')");

If I understand correctly, then you need to filter the data in the collection by "labels" by the specified values. Any / All is just right for this.

If I am not mistaken contains with Ordered Collection support, even if added, will still not help, since it works differently.

ZEXSM commented 3 years ago

resolved#35