how can I create an relationship in NEO4J from one node to another node which has multiple vales.
The first node has unique values for the identifier. For example:
Data of the first NodeA:
{
"c": "11037",
"b": 15.4,
"a": 10.0,
"id": 11137100
}
The second NodeB look like this:
{
"text": "some text",
"prio": 1,
"id": 11137100,
"value": 0.1
}
But here we have data which has the same id like here:
{
"text": "some other text",
"prio": 2,
"id": 11137100,
"value": 2.1
}
Now want to create a relationship between both nodes. But if I do things like:
MATCH (p:NodeA),(h:NodeB)
WHERE h.id = p.id
CREATE (p)-[dr:Contains{prio:h.prio}]->(h)
RETURN (dr)
I get multiple relationships. I want one NodeA with two Outputs to NodeB.
How can I do it?
The CREATE statement will create a new node/relationship, irrespective if one already exists.
If the intent is to only create a relationship if one does not already exist, I would suggest you do a pre-filter query first, e.g.
MATCH (p:NodeA), (h:NodeB)
WHERE h.id = p.id AND NOT (p)-[:Contains{prio:h.prio}]->(h)
//continue your query here
Related
I have two nodes A and B (A->B) connected via two relationships. Those 2 relationships are unique. For example, you can think of the two rels as two paths from A to B at two different times. Converting them to one relationship is not viable at this time.
For displaying in UI, query result should be a tree structure. Used following query to get the tree
MATCH p=(n:Label1 {name:'main'})-[:calls*..2]->(m)
WITH COLLECT(p) AS ps
CALL apoc.convert.toTree(ps) yield value
RETURN value;
the resulting tree is
Preferred result is
How can I get a tree with duplicate children is more than one relationship exists between same two nodes?
Thanks.
I offer a hack on this SO question. Although it is not exactly the resulting nested document as the apoc function but I think it can server your purpose.
MATCH p=(n:Label1 {name:'main'})-[:calls*..2]->(m)
// each path will be returned
WITH COLLECT(p) AS ps, p, n
CALL apoc.convert.toTree(ps) yield value
// return node n and it's relationships as a nested document
RETURN {_id: ID(n), _type: labels(n), node:n, relationships: collect(value['calls'][0])} as result
Sample result:
[
{
"result": {
"_id": 31,
"_type": [
"Label1"
],
"node": {
"name": "main"
},
"relationships": [
{
"calls.y": "prop y",
"_type": "Main",
"_id": 32
},
{
"_type": "Main",
"_id": 32,
"calls.x": "prop x"
}
]
}
}
]
I have the nodes user and game with some relationships between them.
My REST API should return all relationships between the games and 1 user.
The cypher query i use is:
MATCH (u:User {id: '1234'} ) -[rel]- (game:Game) return game{.*, relationships: collect(DISTINCT rel)}
In my Neo4j Browser, everything works as expected and i see all properties i need.
But the GetMapping retuns everything except the relationship properties.
Neo4j Browser
{
"relationships": [
{
"identity": 54,
"start": 9,
"end": 8,
"type": "OWNED",
"properties": {
"ownedDate": "2021-07-03"
}
},
{
"identity": 45,
"start": 9,
"end": 8,
"type": "PLAYED",
"properties": {
"times": 5
}
}
],
"name": "Blood Rage",
"state": "ACTIVE",
"id": "1c152c91-4044-41f0-9208-0c436d6f6480",
"gameUrl": "https://asmodee.de/blood-rage"
}
GetMapping result (As you can see, the relationships are empty, but i have more empty JsonObjects, when there are more Relationships
{
"game": {
"relationships": [
{},
{}
],
"name": "Blood Rage",
"gameUrl": "https://asmodee.de/blood-rage",
"state": "ACTIVE",
"id": "1c152c91-4044-41f0-9208-0c436d6f6480"
}
}
The GetMapping is:
...
final ReactiveNeo4jClient client;
...
...
...
#GetMapping(value = { "/{id}/games"})
#RolesAllowed({"user", "admin"})
Flux<Map<String, Object>> findGamesByUser(#PathVariable String id){
String query = "MATCH (uuser:User {id: '" + id + "'} ) -[rel]- (game:Game) return game{.*, relationships: collect(DISTINCT rel)}";
return client.query(query).fetch().all();
}
A RelationshipProperty-Example
#RelationshipProperties
#Data
#Builder
public class PlayedGame {
#Id
#GeneratedValue
private Long relationshipId;
#Property
int times = 0;
#TargetNode private GameEntity game;
public int addPlay(){
this.times = this.times + 1;
return this.times;
}
}
What do i have to change in my GetMapping to show the relationship-properties?
Thank you,
Kevin
You need to return the actual nodes and relationships, otherwise you're missing the id-mapping.
There should be examples in the SDN docs.
Best if you have a small reproducible example (e.g. with the default movies graph).
Not sure if there is something off in your SDN setup, in general for such simple queries you should be able to just use a repository and not need to write cypher queries by hand.
The general information given by Michael is correct but there is more in you question:
First of all the meta domain model is completely ignored if you are using the Neo4jClient. It does not automatically map anything back but uses the driver's types.
As a result you will end up with an (current state of this answer) InternalRelationship which does not have any getter-methods.
I assume that you are serializing the result in the application with Jackson. This is the reason why you see objects that represent the relationships but without any content within.
If you want to get things mapped for you, create also the domain objects properly and use (at least) the Neo4jTemplate with your query.
If you model User, Game, and the relationship properties like PlayedGame correctly, a
neo4jTemplate.findAll("MATCH (u:User)<-[rel]-(g:Game) return u, collect(rel), collect(g)", User.class)
will map the results properly. Also if this is all you have, you could also skip the custom query at all and use
neo4jTemplate.findAll(User.class)
or
neo4jTemplate.findById(useId, User.class)
I have four nodes that -[belongTo]-> (ContainerNode)
I want the json to return as a single container node which contains an array of all the nodes that link to it. For example:
"nodes": [
{
"id": "240",
"name":"MyNodeContainer",
"Type": "ContainerNode"
"SubNodes": [
{
"id": "1",
"name":"MyNodeA",
"Type": "node"
},
{
"id": "2",
"name":"MyNodeB",
"Type": "node"
}
]
},
It seems simple but all i can get is the default of all nodes being returned as equal. I want the result to make it clear that the container node is separate from the rest. An array property seems most intuitive but i would also be content with two lists - one for the single nodeContainer and one for the contained nodes
Does something like this steer you towards your end goal? It builds a collection of the contained nodes and then returns it as a property of the ContainerNode.
MATCH (c:ContainerNode)<-[:BELONGS_TO]-(n:Node)
WITH c, collect({ id: id(n), name: n.name, type: labels(n)[0] }) AS nodes
WITH { id: id(c), name: c.name, type: labels(c)[0], SubNodes: nodes } AS containerNode
RETURN {nodes: collect(containerNode) }
How can I do multiple Nodes update in neo4j cypher?
Now I'm trying to do like this:
MATCH (user151325288158:User{userId:151325288158}),
(user88245:User{userId:88245})
SET user151325288158.balance=2902833.4219789803
SET user88245.balance=146701.0299999991
RETURN user151325288158.balance,user88245.balance;
But here I have problem that if such user is absent in DB, nobody will be updated.
Other problem is performance, such queries are slow.
Is there some method to do such bulk updates?
Assuming you have pairs of userIds and new balance values in an array of maps/dicts, like this:
[
{
"userId": 151325288158,
"balance": 146701.09
},
{
"userId": 887436512344,
"balance": 22453.34
},
{
"userId": 873927654232,
"balance": 300002.22
}
]
You can pass this array as a parameter to a Cypher query to MATCH on the userId and update the balance property like this:
WITH {data} AS pairs
UNWIND pairs AS p
MATCH (u:User) WHERE u.userId = p.userId
SET u.balance = p.balance
By following William Lyon's answer, I was able to implement a batch update of multiple properties as follows:
UNWIND [{id: 123456, name: "John", age: 27}, {id: 789012, name: "Jane", age: 24}] AS updateUser
MATCH (user: User)
WHERE user.id = updateUser.id
SET user += updateUser
RETURN user
So I have a json (in text field) and I'm using postgresql and I need to query the field but it's nested a bit deep. Here's the format:
[
{
"name":"First Things",
"items":[
{
"name":"Foo Bar Item 1",
"price":"10.00"
},
{
"name":"Foo Item 2",
"price":"20.00"
}
]
},
{
"name":"Second Things",
"items": [
{
"name":"Bar Item 3",
"price":"15.00"
}
]
}
]
And I need to query the name INSIDE the items node. I have tried some queries but to no avail, like:
.where('this_json::JSON #> [{"items": [{"name": ?}]}]', "%#{name}%"). How should I go about here?
I can query normal JSON format like this_json::JSON -> 'key' = ? but need help with this bit.
Here you need to use json_array_elements() twice, as your top level document contains array of json, than items key has array of sub documents. Sample psql query may be the following:
SELECT
item->>'name' AS item_name,
item->>'price' AS item_price
FROM t,
json_array_elements(t.v) js_val,
json_array_elements(js_val->'items') item;
where t - is the name of your table, v - name of your JSON column.