Get OData Children Count with Filter option - odata

I have created a OData service and Parent and Child relationship and I am looking for some help for the below case.
I need to retrieve all the data from Parent and Count of Children records and also want to check if the Children has Specific value. The below query works partially to some extent but it is not solving the purpose.
https://someURL/v1/Events?$expand=Attendees($select=userId;$count=true;$filter=(userid eq 1)
This query will give me the children count after filtering, but I am looking the overall children count for the Parent record.
Note: I don't want to pull all the records to client side and check UserId has 1 in this case.
Thanks,
Suresh

Related

How to Fetch a node and all related nodes in Neo4j

I am looking forward to implement a discussion forum using Neo4j as database.
I want to fetch a question and all its answers and all the comments on the answers using questionId.
In my database all the nodes have label POST and they all have directed relationship "hasComment" POST-hasComment->POST
I have come up with following query:
Match path=((n:POST)-[:hasComment*]->(any)) return path;
This query is returning required data but i am getting a lot of repeated data on relationship between POSTS.
Is there a better way to fetch the information?
This is how nodes and relationship between nodes look like
Assuming you are exporting the data in JSON. You can not change the existing format, like in JSON, it is because a node can have multiple relationship (i.e. parent node can have multiple child node and child can have multiple parent) and current format tracks the parent and child relation info (i.e. who is the parent node of a child in a particular path).
You can filter the result in query itself by using any subquery or using some filters such as use of WHERE clause. or clean the JSON as required.

WIQL nested queries

In ADO I have a single parent work item with child work items. The children work items, in turn have related work items. The number of child items will grow as time progresses.
What I'm trying to get is the list of the related work items. This would be pretty trivial if the list of child work items wasn't growing, but I don't want to have to edit a simple tree query by adding a new work item ID to the top level of the query whenever a new child work item is created.
Is there a way in WIQL that I can write a query that effectively says, "get the children of item #xxxxx, then get the related items for each of those children?"
If you have a single known parent that will never change, all you need to do is create a query with the following parameters:
Type of query: Tree of work items
Type of tree: Parent/Child
In your filters for top level work items, specify the parent work item ID. In your filters for linked work items, don't specify anything. All work items that live below the parent will be returned, with the parent at the top of the query.

Neo4j Cypher - Returning nodes and their nested nodes of the same type

I want to be able to return a list of Item nodes with their list of nested Item nodes contained within a Box. Because the relationships between the Item nodes and their nested Item nodes may be different (E.g. WHEELS, WINDOWS, LIGHTS), I would like to write a query that skips over the relationships and returns any nested Item node and their Item children because an Item will either have at least one Item child or none (thus resulting in empty children list).
I want to be able to do this with just a Box identifier (E.g. boxID) being passed.
NOTE: I'm new to Neo4j and Cypher so please reply with a (fairly) detailed answer of how the query works. I want to be able to understand how it works. Thanks!
E.g.
MATCH (iA: Item)-[r]->(iB: Item)-[r]->(b: Box)
WHERE b.boxID = $boxID
RETURN COLLECT(iB.itemID AS ItemID, ib.name as ItemName, COLLECT(iA.itemID as ItemID, iA.name as ItemName, COLLECT(...) ) AS ItemChildren)
The COLLECT(..) part confuses me. How do I return an Item node and all of its Item children and all of that childs Item children, and so on until empty children? Is there a better way to MATCH all of the nodes?
That is very easy using a variable-length relationship pattern:
MATCH (b:Box)-[:CONTAINS]->(:ItemInstance)-[*]-(i:Item)
WHERE b.boxID = $boxID
RETURN COLLECT(DISTINCT i) AS ItemChildren
The DISTINCT option is needed because the variable-length relationship result can return the same item multiple times.
This query also acknowledges the relationship directionality shown in your diagram. The CONTAINS relationship pattern specifies the appropriate directionality, but the variable-length relationship (-[*]-) specifies no directionality since your data model does not use a consistent direction throughout the tree starting at an ItemInstance.
Caveat: unbounded variable-length relationships can take a very long time or even run out of memory, depending on how big your DB is and how many relationships each node has. This can be worked around by specifying a reasonable upper bound on the length.

Neo4j ordered tree

We are working with a hierarchy tree structure where a parent has zero or more children, and a child has either one or zero parents. When we query for a list of direct children for a given parent the query returns the children in random order. We need the children to return in the order we define when we create or update the children.
I have added a relationship between children -[:Sibling]-> so the 'top' sibling has only an incoming :Sibling relationship, and the 'bottom' sibling has only an outgoing relationship.
Given this, is there a Cypher query to return the children in sibling order?
I have a query that returns each child, and its sibling, but now I have to write some code to return the list in the correct order.
An alternative approach might be to add a sort number to each child node. This would need to be updated for all the children if one of them changes order. This approach seems slightly foreign to the graph database concept.
If this problem has been encountered before, is there a standard algorithm for solving it programatically?
Update1
sample data as requested by Bruno
(parent1)
(child1)-[:ChildOf]->(parent1)
(child2)-[:ChildOf]->(parent1) (child2)-[:Sibling]->(child1)
(child3)-[:ChildOf]->(parent1) (child3)-[:Sibling]->(child2)
is there a cypher query to return child1, child2, child3 in that order?
if not, then the ordering can be done programatically
using properties instead of relationships
(parent1)
(child1)-[:ChildOf]->(parent1) (child1:{order:1})
(child2)-[:ChildOf]->(parent1) (child2:{order:2})
(child3)-[:ChildOf]->(parent1) (child3:{order:3})
`match (c)-[:ChildOf]->(parent1) return c ordered by c:order`
I do not expect that there is a cypher query that can update the order of children.
Update2
I have now arrived at the following query which returns children in the right order
`match (firstChild)-[:FirstChildOf]->(parent) match (sibling)-[:Sibling*]->(firstChild) return firstChild,sibling`
This query depends on adding a -[:FirstChildOf]->(parent) relationship.
If I don't hear otherwise I'll set this to the answer.
Shall I assume there is no cypher query for inserting a node into an ordered list?
When you create your graph model you should concentrate on the questions you want to answered with your data model.
If you want to get child of a parent ordered by a "create or update" property then you should store it since the relationship in general does not represent an order.
It is not foreign to the graph database concept, since the graph databases use properties. It is not always easy task to decide
to store something as a relationship or a property. It is all about the proper modelling.
If you have the concept of '[:NEXT_SIBLING]' or similar, then it will be a pain in the back, when you have to remove a node. So I should use it when this state is constant. For example in a timetree, where the days are after each other and it does not change.
In general, if the creation order should be used, I should use timestamps like this:
create (n:Node {created:timestamp()});
Then you can use the timestamp to order.
match (p:Parent)-[:HAS_CHILDREN]->(n:Child) where p.name='xy' return n order by n.created;
And you can use timestamps for relationships too.
Similar question is here:
Modeling an ordered tree with neo4j
Here are some tips I use for dealing with ordered lists of nodes in Neo4J.
Reverse the relation direction to (child1)<-[:HasChild]-(parent1). (mostly just logical reinforcement of the next items, since a "parent has list of children")
Add the property index to HasChild. This will let you do WITH child, hasChild.index as sid ORDER BY sid ASC for sibling order. (This is how I maintain arbitrary order information on lists of children) This is on the relationship because it assumes that a node can be part of more than one ordered list.
You can use SIZE(shortestpath((root)-[*]->(child1)) as depth to then order them by depth from a root.
Since this is for arbitrary order, you must update all the indexes to update the order (You can do something like WITH COLLECT(child) as children, FILTER(c IN COLLECT(child) WHERE c.index >=3) as subset FOREACH (c IN subset| SET c.index+=1) for a basic insert, otherwise you will have to just rewrite them all to arbitrarily change the order.
If you don't actually care about the order, just that it is consistent, you can use WITH child, ID(child) as sid ORDER BY sid ASC. This essentially is "Order by node age"
One other option is to use a meta relationship. So :HasChild would act as a list of nodes, and then something like :NextMember would tell you what the next item from this one is. This is more flexible, but in my opinion harder to work with (You need to case for doesn't have next, to get the right order you have to do a 'trace' on the nodes, doesn't work if you want to add this node to another ordered list later, ect.)
Of course, if the order isn't arbitrary (based on name or age or something), than it is much better to just sort on the non-arbitrary logic.
The query for returning the children in the right order is
match (firstChild)-[:FirstChildOf]->(parent) match (sibling)-[:Sibling*]->(firstChild) return firstChild,sibling

Neo4J : intersection and predicates

I'm working on a project involving Neo4J Db and I'm facing a problem I can't solve by myself.
We are dealing with Acl in a graph. Each Acl is linked to a set of metadata. Items are also linked to those metadata. A metadata grants access to one item when ALL the metadata linked to the item are also linked to the metadata.
Here is a picture of the graph model:
ACL graph picture
In this example, ACL1 grants access to item1 (but not item2), and acl2 grants access to item2(but not item1).
I think the trick is to use the ALL predicate on the nodes linke to one item, but my tries always return all the items from the graph (because they are sharing one meta)
Can someone helps me to create the cypher query to returns for one user all the items he can access ?
Thanks for your help, Gregory
PS : here is a Neo4j console example dataset : http://console.neo4j.org/r/urjh64
Using the ALL predicate is the correct way here. How about this query:
MATCH (:User { Login:'User1' })-[:IS_GRANTED]->(acl)-[:IS_APPLICABLE]->(meta)-[:IS_APPLICABLE]->(item)
WITH item, collect(meta) AS userMetas
MATCH (item)<-[:IS_APPLICABLE]-(meta2)
WITH item, userMetas, collect(meta2) AS itemMetas
WHERE ALL (x IN itemMetas WHERE x IN userMetas)
RETURN item
First we navigate from the user to all items he potentially has access to. For the candidates we go back and collect all metas. In the WHERE we make sure that all of the metas of the item are also available for the user.

Resources