-
Notifications
You must be signed in to change notification settings - Fork 416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MERGE
creates incomplete vertices after the first one
#1709
Comments
MERGE
creates incomplete vertices if the RETURN
clause does not include the created verticesMERGE
creates incomplete vertices after the first one
The issue you're encountering with MERGE creating incomplete vertices stems from the way the MERGE and SET commands are being applied. In your query, MERGE is used with a condition that solely relies on the first property to identify unique vertices. However, this approach can lead to unexpected results when the first property alone does not uniquely identify a vertex, as MERGE will match existing vertices based on the first property and might not correctly associate the last property with subsequent vertices. To ensure each vertex is accurately created or matched with its complete set of properties (first and last), you need to adjust the MERGE condition to include all properties that together uniquely define a vertex. The combination of first and last names uniquely identifies a PERSON vertex, therefore both should be included in the MERGE condition to prevent the creation of incomplete vertices. |
@anfa-majid |
I think we can fix this issue by explicitly assign each property indivisually in merge operation //previous line //updated line In this updated query, after the MERGE operation, we set each property first and last separately from the map variable, which should ensure that all vertices have both "first" and "last" fields correctly set. |
@Akaza20-03 |
@mingfang It looks like maybe my PR #1718 might have fixed this one too?! This is in the master branch, btw.
|
@mingfang Oops, nvm, sigh,...
|
@mingfang I will look into this one. It looks like it is creating the correct return tuple, just not inserting the correct tuple. I sometimes think that I should just rewrite merge altogether. |
@mingfang Question - Just curious, why are you doing it this particular way? If you use merge as follows, it works -
I'm thinking this might be an issue with SET, and not MERGE. |
My real use case is to create a graph from a SQL query and I don't know ahead of time what fields are returned. -- Apache AGE load_sql
CREATE OR REPLACE FUNCTION public.load_sql(query agtype) RETURNS SETOF agtype AS $$
BEGIN
RETURN QUERY EXECUTE FORMAT($sql$
WITH query AS (%s)
SELECT agtype_build_list(query)
FROM query
$sql$, query::text);
END
$$ LANGUAGE plpgsql VOLATILE; Then in cypher is would call that function and use MERGE to create graph. SELECT * FROM cypher('movies', $$
UNWIND public.load_sql('
SELECT * FROM movies
') AS row
MERGE (v:MOVIE {title: row.title})
SET v=row
RETURN count(v)
$$) AS (v agtype); |
@mingfang I traced the code and found it skipping the insert for the latter tuple. This looks to be a transaction/command id issue. |
The issue you're encountering is because of the way you're merging and setting properties in your Cypher query. When you use MERGE, it will only create a new node if it doesn't already exist with the specified properties. However, in your case, you're using SET after MERGE, which can overwrite existing properties on the node. To fix this issue and ensure that properties are correctly set for all nodes, you should use ON CREATE SET in addition to SET. This will only set properties if the node is newly created during the MERGE operation. Here's the corrected query: SELECT * FROM cypher('playground', $$ |
@diangamichael Could you, in addition to your response, include an example using Apache AGE showing this solves the issue? |
@mingfang Yeah, it appears to be an issue with transaction/command ids. It likely has to do with the handoff between MERGE and SET as both are updates. |
The issue you're encountering is due to the behavior of the SET clause in your Cypher query. When you use SET v=map, you're overwriting all properties of the node v with the properties from the map. If the map doesn't contain a certain property (like "last" in the case of the second iteration), it will effectively remove that property from the node. To fix this issue, you can modify your query to conditionally set properties only if they exist in the map. Here's how you can do it: SELECT * FROM cypher('playground', $$ |
I second the idea of implementing ON CREATE and ON MATCH. A few neo4j examples as food for thought: MERGE (keanu:Person {name: 'Keanu Reeves'})
ON CREATE
SET keanu.created = timestamp()
ON MATCH
SET keanu.lastSeen = timestamp()
RETURN keanu.name, keanu.created, keanu.lastSeen MERGE (person:Person)
ON MATCH
SET
person.found = true,
person.lastAccessed = timestamp()
RETURN person.name, person.found, person.lastAccessed |
@sir-sa Respectfully, that is not how SET works internally nor is it the cause of this issue. What is interesting, though, is that your query works. But, it also works without the conditional part, highlighting what I've stated and pointing again to transaction/command ids. |
@jtomek ON CREATE or ON MATCH may be good to add to Apache AGE. You should consider opening a separate discussion thread about them to see what others might think. Unfortunately, for this particular issue, this is just a bug that needs to be fixed. |
@mingfang From the example above I have a possible workaround for you while I figure out what the issue is with the ids -
|
@jrgemignani |
@mingfang Don't get too carried away ;) it is just a temporary workaround. We shouldn't need to run SET twice to get it to work. |
@mingfang I found the issue and corrected it. Although, I need to review that it is correct and there aren't other areas that may have a similar issue. Here is a sample output that also highlights something interesting. I'm curious of your thoughts -
Note that the correct data is stored in the end. |
Let's close this bug since the earlier suggestion works perfectly 🙂🙂🙂 |
@diangamichael Thank you for your input. However, this issue is a bug and the suggestion is a temporary workaround. This issue cannot be closed until the issue is resolved and @mingfang, who opened the issue, is satisfied with the solution. |
@jrgemignani |
when creating multiple vertices like this
returns 2 vertices, but all the vertices after the first one will be incomplete. e.g.
returns
Note the first vertex is correct but the second vertex is missing the "last" field. Very strange.
The text was updated successfully, but these errors were encountered: