Cypher: How to merge two nodes' keys in a third node - database

in cypher i want to create a node that has attributes of two existing nodes. I know that to "copy" a node the query is: MATCH (old:Type) CREATE (new:Type) SET new=old but this allow me to have the keys from just one node. I need a way to join the keys of two nodes and copy that node
match (a:Ubuntu1604), (h:Host) CREATE (b:Ubuntu1604) SET b=a,b=h return b
will obviously create b equals to h. I need and "append" function

I figured out myself.
Solution is simply
match (a:Ubuntu1604), (h:Host) CREATE (b:Ubuntu1604) SET b=a, b+=h return b

Related

To get nodes from a subgraph that are connected to a particular node

To explain the problem i have to optimize a cypher query where i am getting nodes connected to a particular node after the subgraph is formed
The query looks like -
match (node{property})
apoc.call.subgraphnodes(
rel filter (has_X,is_y),
label filter (+x|/y|>z))
match (z)-[is_y]-(y)
return collect(z.id)
Problem statement:
Question 1. Is there any way to avoid match statement so that the number of db hits can be reduced
Question 2. Is there a possibility in which i return relationships using subgraphAll and apply filter on a list of relationships like TYPE(relationships) = "is_y"

Arangodb update properties depend on edge type

I am trying to use AQL to update the whole node collection , named Nodes, depend on the type of edges they have
.
Requirement:
Basically, if 2 entity in Nodes has relation type= "Same", they would be updated with unique groupid properties (same for more than 2)
This would only run one time in the beginning (to populate groupid)
My concept approach:
Use AQL
For each entity inside Node, query out all connectable nodes with type=SAME
Generate an groupid and Update all of them
Write to an lookup object those id
For next entity, do a lookup, skip the entity if their id is there.
What I tried
FOR v,e,p
In 1..10
ANY v
EntityRelationTest
OPTIONS {uniqueVertices:"global",bfs:true}
FILTER p.edges[*].relationType[0]== "EQUALS"
UPDATE v WITH { typeName2:"test1"} IN EntityTest
return NEW
But I am quite new to arangodb AQL, is something like above possible?
In the end, what I use is a customize traversal object running directly inside Foxx in order to get the best of both world: performance and correctness. It seemed that we cannot do the above with only AQL

clone some relationships according to a condition

I exported two tables named Keys and Acc tables as CSV files from SQL Server and imported them successfully to Neo4J by using the commands below.
CREATE INDEX ON :Keys(IdKey)
USING PERIODIC COMMIT 500
LOAD CSV FROM 'file:///C:/Keys.txt' AS line
MERGE (k:Keys { IdKey: line[0] })
SET k.KeyNam=line[1], k.KeyLib=line[2], k.KeyTyp=line[3], k.KeySubTyp=line[4]
USING PERIODIC COMMIT 500
LOAD CSV FROM 'file:///C:/Acc.txt' AS line
MERGE (callerObject:Keys { IdKey : line[0] })
MERGE (calledObject:Keys { IdKey : line[1] })
MERGE (callerObject)-[rc:CALLS]->(calledObject)
SET rc.AccKnd=line[2], rc.Prop=line[3]
Keys stands for the source code objects, Acc stands for relations among them. I imported these two tables three times for three different application projects. So to maintain IdKey property being unique for three applications, I concatenated a five character prefix to IdKey to identify the Object for Application while exporting from sql server because we can not create index based on multiple fields as I learnt from manuals. Now my aim is constructing the relations among applications. For example:
Node1 is a source code object of Application1
Node2 is another source code object of Application1
Node3 is a source code object of Application2
There is already a CALL relation created from Node1 to Node2 because of the record in Acc already imported.
The Name of the Node2 is equal to name of Node3. So we can say that Node2 and Node3 are in fact the same source codes. So we should create a relation from Node1 to Node3. To realize it, I wrote a command below. But I want to be sure that it is correct. Because I do not know how long it will execute.
MATCH (caller:Keys)-[rel:CALLS]->(called:Keys),(calledNew:Keys)
WHERE calledNew.KeyNam = called.KeyNam
and calledNew.IdKey <> called.IdKey
CREATE (caller)-[:CALLS]->(calledNew)
This following query should be efficient, assuming you also create an index on :Keys(KeyNam).
MATCH (caller:Keys)-[rel:CALLS]->(called:Keys)
WITH caller, COLLECT(called.KeyNam) AS names
MATCH (calledNew:Keys)
WHERE calledNew.KeyNam IN names AND NOT (caller)-[:CALLS]->(calledNew)
CREATE (caller)-[:CALLS]->(calledNew)
Cypher will not use an index when doing comparisons directly between property values. So this query puts all the called names for each caller into a names collection, and then does a comparison between calledNew.KeyNam and the items in that collection. This causes the index to be used, and will speed up the identification of potential duplicate called nodes.
This query also does a NOT (caller)-[:CALLS]->(calledNew) check, to avoid creating duplicate relationships between the same nodes.

How can I delete all the records which varchar contains any of a list of elements?

I have Trees:
Trees(IDNodo, Path, color, ....)
IDMytable is a autonumeric (bigint) and path is a varchar(MAX) that contains the complete route to a node in my tree.
I would like to delete all the nodes and subnodes, so I can do:
delete from trees where Path like '%[IDNode]'%
This delete the node and all the subnodes.
But if I want to delete all the nodes that have an specific property, I can get these nodes with this query:
select * from Trees where Color = 'Red';
This gives me all the nodes in all the trees that are red. I get many IDNodes. Then I want to delete all the subnodes of each red node.
delete from trees where Path like IN (select * from Trees where Color = 'Red');
If path is a long, for example, I can use "IN" but I don't know if there is an equivalent when the field is a varchar.
I would like to avoid the use of a recursive procedure.
You want to make your delete query like below
delete from trees where Path
IN (select Path from Trees where Color = 'Red');
But the above query is same as saying
delete from Trees where Color = 'Red';

Neo4j: Step by Step to create an automatic index

I am creating a new Neo4j database. I have a type of node called User and I would like an index on the properties of user Identifier and EmailAddress. How does one go setting up an index when the database is new? I have noticed in the neo4j.properties file there looks to be support for creating indexes. However when I set these as so
# Autoindexing
# Enable auto-indexing for nodes, default is false
node_auto_indexing=true
# The node property keys to be auto-indexed, if enabled
node_keys_indexable=EmailAddress,Identifier
And add a node and do a query to find an Identifier that I know exists
START n=node:Identifier(Identifier = "USER0")
RETURN n;
then I get an
MissingIndexException: Index `Identifier` does not exist
How do I create an index and use it in a start query? I only want to use config files and cypher to achieve this. i.e. at the present time I am only playing in the Power Tool Console.
Add the following to the neo4j.properties file
# Autoindexing
# Enable auto-indexing for nodes, default is false
node_auto_indexing=true
# The node property keys to be auto-indexed, if enabled
node_keys_indexable=EmailAddress,Identifier
Create the auto index for nodes
neo4j-sh (0)$ index --create node_auto_index -t Node
Check if they exist
neo4j-sh (0)$ index --indexes
Should return
Node indexes:
node_auto_index
When querying use the following syntax to specify the index
start a = node:node_auto_index(Identifier="USER0")
return a;
As the node is auto indexed the name of the index is node_auto_index
This information came from a comment at the bottom of this page
Update
In case you want to index your current data which was there before automatic indexing was turned on (where Property_Name is the name of your index)
START nd =node(*)
WHERE has(nd.Property_Name)
WITH nd
SET nd.Property_Name = nd.Property_Name
RETURN count(nd);
Indexes mainly made on property which is used for where condition. In Neo4j 2.0, indexes are easy to make now.
Create index on a label
CREATE INDEX ON :Person(name)
Drop index on a label
DROP INDEX ON :Person(name)
Create uniqueness constraint
CREATE CONSTRAINT ON (book:Book) ASSERT book.isbn IS UNIQUE
Drop uniqueness constraint
DROP CONSTRAINT ON (book:Book) ASSERT book.isbn IS UNIQUE
For listing all indexes and constraints in neo4j-browser, following command is useful
:schema
List indices and constraints for specific label with:
:schema ls -l :YourLabel
In Neo4j 2.0, you should use labels and the new constraints instead
CREATE CONSTRAINT ON (n:User) ASSERT n.Identifier IS UNIQUE
CREATE CONSTRAINT ON (n:User) ASSERT n.EmailAddress IS UNIQUE
If email isn't unique per user, just create a plain index instead:
CREATE INDEX ON :User(EmailAddress)

Resources