How do you query an OData Collection of Enumerations? - odata

I have been searching for the definitive answer on this but can't seem to find it anywhere. What I do know is that it's legal to create a Collection of the OData 4.0 Enumeration type. I also know that the Olingo parser that we are using (4.2) allows us to query both an Enumeration or Collection of Enumeration using the 'has' keyword. What I can't find, however, is any documentation that proves that this is actually a legitimate query. I also know that using OLingo and Microsoft parsers, that the any/all syntax that would generally be used for a Collection does not seem to work. I would really appreciate any help figuring this out.

The OData version 4 spec says this about logical operators: "Operands of collection, entity, and complex types are not supported in logical operators." has is one of the logical operators. Therefore, has is not supported on a collection of enumeration type. Furthermore, has is defined to operate on a single enumeration value, so it is not appropriate for querying a collection of enumeration values.
The spec also says that the lambda operators operate on "a navigation path that identifies a collection". If navigation path means a path that ends with a navigation property, then any/all can only be applied to a collection identified by a navigation property. Since collections of enumeration type are represented by structural properties, it follows that any/all cannot be applied to collections of enumeration type. But this is conjecture, since the term navigation path is not defined in the spec.
In lieu of a collection of enumeration type, consider using an enumeration type that has the IsFlags attribute set. You can definitely query such an enumeration using the has operator.

Related

Is there a method to splt a Map based on the FIRST node to satisfy a predicate?

There is a function called Map.partition that splits the map into 2 maps with one containing ALL elements that satisfy the predicate. The predicate takes a key and a value as arguments and examines each element of the map to determine which result map it belongs to.
My requirement is a special case of this. I have a map and I want to split into 2 maps based on whether or not the key is greater than or less than some value.
This would be much more efficient as you only have to search the tree until the output of the predicate changes. The current implementation would be O(n) and what I am looking for would be O(log(n)). This should be straight forward for a custom tree implementation but I would prefer to use the built in collections if I can, before I roll my own.
The documentation for the F# Maps can be found in the following link: https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/collections.map-module-%5Bfsharp%5D
Altough the operation you want to implement could be implemented in O(log(n)), it is not implemented in this module. The best option would be to use partition (would be O(n), as you said) or implement your own version of Map. You could also search for some code in github which implements a Red-Black Tree and include your own custom method for this operation.
Short Answer: No, there is not a method to split a Map based on the first node to satisfy a predicate.
EDIT: this -> the

Collection? Dictionary? List?

Neo4j's manual does a very good job at explaining the meaning of the terms Node, Relationship, Label and a few others.
However, the real vocabulary of Cypher seems to include quite a few elusive terms, as well.
For instance, clause 3.3.15.1 of the manual says "Lists and paths are key concepts in Cypher". Fine, but what is a List in Cypher? I have all but given up trying to find a definition of that "key concept".
Similarly, the Cypher Reference Card mentions that "Cypher also supports maps and collections". Elsewhere, one can find that Cypher also "works with dictionaries".
Needless to say, I am in the dark as to how to spot and/or use those in Cypher.
Would really appreciate some illustrations.
Thanks.
The docs has a section on Composite types:
3.2.1.3. Composite types
✓ Can be returned from Cypher queries
✓ Can be used as parameters
❏ Cannot be stored as properties
✓ Can be constructed with Cypher literals
Composite types comprise:
Lists are heterogeneous, ordered collections of values, each of which has any property, structural or composite type.
Maps are heterogeneous, unordered collections of (key, value) pairs, where:
the key is a String
the value has any property, structural or composite type
You might also be interested in the development of openCypher. One of the goals of the openCypher project is to define the concepts of the Cypher language. As stated on its homepage:
The openCypher project aims to deliver a full and open specification of the industry’s most widely adopted graph database query language: Cypher.
Currently, openCypher is a work-in-progress. It has a draft document on the Property Graph Model, which itself does not discuss lists/maps in detail, but refers the CIP2015-06-16 - Public Type System and Type Annotations document, which is an accepted Cypher Improvement Proposal. It has a section on "Container Types", which defines how lists and maps work in Cypher.
I have not seen the term "dictionary" in the core Neo4j docs. It could be mentioned around drivers though, as some languages, e.g. Python, use this term for maps.
(Disclaimer: I am a regular participant at the openCypher Implementers Group meetings.)
According to wikipedia :
https://en.wikipedia.org/wiki/List_(abstract_data_type) : a list (or sequence, collection) is a data type that represents a countable number of ordered values.
https://en.wikipedia.org/wiki/List_(abstract_data_type) : a map (or dictionnary) is a data type composed of a collection of (key, value) pairs.
And in Cypher :
this is a list : RETURN ['Benoit', 'Simard'] AS list
this is a map : RETURN { firstname:'Benoit', lastname:'Simard'} AS map
Cheers

How to match nodes only by value? (not defining specific property)

I want to search nodes by value only, which can be in any of node properties. I know that this is an expensive operation, but nodes will be cut off by some relationship conditions.
I want something like this:
MATCH (n: {*:"Search value"})
RETURN n
Where * imply "any property".
Is there a way to do this?
interesting tidbits can be found in this abstract regarding this topic and why it might not be implemented
https://docs.google.com/document/d/1FPfGkgzhcRXVkleBLBsA92U94Mx4yafu3nO-Xf-NzsE/edit#heading=h.pyvdg2rbofq
Semantics of dynamic key expressions
Using a dynamic key expression like <mapExpr>[<keyExpr>] requires that <mapExpr> evaluates to a map or an entity, and that <keyExpr> evaluates to a string. If this is not the case, a type error is produced either at compile time or at runtime.
If this is given, evaluating <mapExpr>[<keyExpr>] first evaluates keyExpr to a string value (the key), and then evaluates <mapExpr> to a map-like value (the map). Finally the result of <mapExpr>[<keyExpr>] is computed by performing a lookup of the key in the map. If the key is found, the associated value becomes the result. If the key is not found, <mapExpr>[<keyExpr>] evaluates to NULL.
Thus the result of evaluating <mapExpr>[<keyExpr>] can be any value (including NULL
Caveats
Dynamic property lookup might entice users to encode information in property key names. This is bad practice as it interferes with planning, leads to unnatural data models, and might lead to exhausting the available property key id space. This is addressed by issuing a warning when a query uses a dynamic property lookup with a dynamic property key name.
To my knowledge, no. Seems to me that what you really are trying to do would be better achieved by creating a search index over the graph using something like elasticsearch or solr. This would give you the ability to search over all properties. Your choice of analyzer whilst indexing would give you the option of exact or partial value matches.

Specifying the primitive type of a property in a Cypher CREATE clause

Contrary to what's possible with the Java API, there doesn't seem to be a way to specify whether a numeric property is a byte, short, int or long:
CREATE (n:Test {value: 1}) RETURN n
always seems to create a long property. I've tried toInt(), but it is obviously understood in the mathematical sense of "integer" more than in the computer data type sense.
Is there some way I'm overlooking to actually force the type?
We have defined a model and want to insert test data using Cypher statements, but the code using the data then fails with a ClassCastException since the types don't match.
If you run your cypher queries with the embedded API then
you can provide parameters in a hashmap with the correctly typed values.
For remote users it doesn't really matter as it goes through JSON serialization back and forth which looses the type information anyway. So it is just "numeric".
Why do you care about the numeric type?
you can also just use ((Number)n.getProperty("value")).xxxValue() (xxx = int,long,byte)

Esper - how to build dissent "statement factory"?

using Esper engine - I find myself write lots of String SQLs, and do lots of string actions to insert query to EPStatement object.
What is the best practice to build queries in more convenient way? maybe build queries not with pure strings but with objects? (Have anyone used EPManagedStatement object?)
There is also the Statement Object Model.
With these classes you can build statements in a more object-oriented way and avoid all the string queries.
Taken from the documentation:
The statement object model is a set of classes that provide an object-oriented representation of an EPL or pattern statement. The object model classes are found in package com.espertech.esper.client.soda. An instance of EPStatementObjectModel represents a statement's object model.
The statement object model classes are a full and complete specification of a statement. All EPL and pattern constructs including expressions and sub-queries are available via the statement object model.
If you find that you are writing a lot of free-form EPL that only varies greatly by the actual values you are inserting, one approach you might find lightens up the amount of code is to use prepared statements ( (EPPreparedStatement). That way, you write the EPL once and then simply issue binds without having to re-specify the text all over again.

Resources