How can I convert an OData QueryNode to a LINQ expression? - linq

This is what I want to achieve:
Get a filter expression from ODataQueryOptions.Filter.FilterClause.Expression
Use a visitor to copy and adjust the filter expression
Use something similar to ODataQueryOptions.ApplyTo(IQueryable query) to apply the modified filter expression to an IQueryable.
Is there maybe some helper in any of the Microsoft OData libraries to do this?

You can refer to code in FilterBinder.

Related

How to extract QueryString value using NiFi processor/language expression?

I am wondering how to extract a querystring value from incoming url using NiFi.
Initially, I started by implementing UpdateAttribute:
For example, I would like from the incoming url http://smth.net/hello?val=23
to have value of 23 extracted.
Further, I expect that I can use that extracted value by referencing it in following way:
(InvokeHttp processor) http://some.net/getValues?id=${q}
Any hints appreciated!
Edited question:
The flowfile inspect after extracting query string looks like:
you could use UpdateAttribute with replaceAll (regular expression):
${url:replaceAll('.*[\\?\\&]val=([^&]*).*','$1')}
maybe regexp could be optimized...
Actually, the easiest possible way to retrieve a query string value is by using NiFi's expression like: ${http.query.param.[keyNameOfQueryString]}.. So, if the request URL is 127.0.0.1/hello?val=23 then the NiFi expression would be ${http.query.param.val}
Other way to do is using regex, as daggett suggested, but in my case I had to do the following:
${http.query.string:replaceAll('val=(\d+).*', '$1')}
Note http.query.string in place of url.

OData "contains" vs Dynamics 365 Web API "contains"

When querying Dynamics 365 via the Web API there are several operators to choose from to filter the queried data. One of those operators is contains which actually appears twice.
One is the OData contains function (you'll find it under the heading 'Standard query functions'):
https://msdn.microsoft.com/en-us/library/gg334767.aspx#Filter%20results
Example:
$filter=contains(name,'(sample)')
The other one is an implementation of the Dynamics 365 Web API itself:
https://msdn.microsoft.com/en-us/library/mt608053.aspx
I tried with this one, but only got a Generic SQL error:
$filter=Microsoft.Dynamics.CRM.Contains(PropertyName='name',PropertyValue='(sample)')
What's the difference? And maybe someone can even tell me how to call the Web API version of contains correctly?
Latest documentation confirms $filter=contains(name,'(sample)') is the only working syntax with web api. As Jatin says, OData filter is converted into Query Expression behind the scenes, some articles (this & this) conveys possible solution is using Like operator directly in C# Query Expression.
We don't have Like operator equivalent functions in web api.
My attempts & observations:
Microsoft.Dynamics.CRM.Contains - Generic SQL error.
$filter=like(name,'%test%') - An unknown function with name 'like' was found. This may also be a function import or a key lookup on a navigation property, which is not allowed.
$filter=contains(name, 'test') - working
I think both methods are equivalent. The Web API filter function is added to support a standard OData filter function. The Contains function is a result of exposing all condition operators supported within CRM as OData functions. Please search ConditionOperator enumerations in D365 documentation for information about the Contains operator. It mentions the reason behind SQL error. Copying the same below:
You must use the Contains operator for only those attributes that are enabled for full-text indexing. Otherwise, you will receive a generic SQL error message while retrieving data. In a Microsoft Dynamics 365 default installation, only the attributes of the KBArticle (article) entity are enabled for full-text indexing.
It is preferable to use Web API filter function since it's more idiomatic. What error do you encounter using it? I suppose the root cause for both might be same since the OData filter query gets converted to D365 query expression in the back end and contains filter should be getting translated to the Contains condition operators.

does sitecore query support current() function?

I get an error if I try to use the xpath 'current()' function in a sitecore query inside a nested expression, something like this:
/sitecore/content/Home/Topics/*[contains(current()/#MainTopics, ##id)]
What I am trying to do is, use this query as a source for my DropLink field to only list 'Topic' items that are already selected in another 'MainTopics' field in the same item.
But this gives me an error, something like ")" expected at position 50
So looks like current() function cannot be used inside the nested expression, or entirely. If not, is there any way to reference the current node and not the context node from within a nested expression?
Any ideas?
does sitecore query support current() function?
current() is a function defined only in XSLT.
By definition current() produces the node that is matched by the current xsl:template or the node that is selected in an xsl:for-each
As SiteCore doesn't seem to have an XSLT implementation, the answer must be negative.
I don't think there's any simple way to do this in Sitecore query.
But to place a data source on a template field that references items chosen in another field (if I've understood right) then one possible solution is to build a custom field. In the code for the custom field you would do some string handling to extend or override Sitecore query, allowing you to add a query type that specified a particular field ID. Essentially you'd have to write your own very basic query language that you could use within your C# code.
You can derive your feild from ValueLookupEx and override the GetItems(Item current) method with your custom query handling. As you can see, it quite handliy comes with the current item provided!
We had a similar requirement which we solved this way.

OData $filter substringof applied to a list of strings

I have an ASP.NET Web API Controller that exposes an IQueryable(Of String) - which is a list of descriptions. These fields can be in the order of tens of thousands, thus I use $top and $skip to only get a chunk of it - that works fine.
Now I am trying to filter these results, through the OData substringof('mydesc',Property) filter. As you can see, it requires for me to pass in a Property name on which to filter. However, since I'm returning a list of strings, I don't actually have any properties to filter on.
This causes the server to return errors like
No property or field 'tostring' exists in type 'String' - when called with $filter=substringof('asd',tostring).
If I change the call to $filter=substringof('asd',''), no errors are thrown, but no results either.
My question is, can I somehow format the $filter operator to find substrings within my list of strings, without looking for a property/field, or am I going to have to declare a class with a single property, just to enable filtering?
Things have changed since the last time I answered this. OData V3 has support for querying collection of primitives using '$it'. Asp.net Web API supports this syntax as well. For example, in your controller you can return IQueryable<string> and send a request like
$filter=substring('mydesc', $it) or
$filter=length($it) ge 5
etc. You can also expose collections of other primitives like IQueryable etc.
unfortunately declaring a class with a single property seems to be the only solution that I can think of. OData $filter doesn't have any support for something like the this parameter in C#
another less obvious approach is to expose a computed concatenated value representing the list, substringof could then be used to query the list as a single property value

Is it possible to do a "not equals" query in Dojo Grid?

I have a Dojo Grid that I'm filtering with a query that's set in a javascript function.
function filter() {
var grid = dojo.byId("gridNode");
grid.setQuery({fieldName:"Some Text"});
}
What I'd really like to do, though, is filter it so that it shows all entries where the fieldName value is not empty. Does anyone know if there's a way to do this with the Dojo Grid Query, or any other solution that will work with Dojo Grid?
If you are using dojo 1.4 and an dojo.data.ItemFileReadStore you can use a regular expression so the following should work:
grid.setQuery({fieldName:"[^]+"});
According to the following documentation page, not all of the data stores may implement regular expression usage in the query but you can try it out:
http:(slash)(slash)docs.dojocampus.org/dojo/data/ItemFileReadStore
(replace slash slash with //, as a new user, spam prevention prevents me from posting more than one hyperlink)
You might also want to look into using the filter property of the Grid to accomplish what you want, if you want to filter based on some input. Look at this example:
http://docs.dojocampus.org/dojox/grid/DataGrid#filtering-data
It would basically just be something like:
grid.filter({fieldName:"[^]+"});

Resources