0
votes

I am facing an issue while I am trying to execute a query in neo4j.

The expected result is to get the products that belong to a certain marketplace and have relation to ProductFeed, starting from marketplace

Query

MATCH (marketplace:`Marketplace`), 
(marketplace)-[rel_has_product_products:HAS_PRODUCT]->(products:`Product`),
 (product:`Product`), 
(product)-[rel_has_product_feed_productFeed:HAS_PRODUCT_FEED]->(productFeed:`ProductFeed`) 
WITH product, 
count(productFeed) AS productFeed_count
 WHERE id(marketplace) = 123481 
and productFeed_count >= 1 
RETURN product 

The error I get is marketplace not defined (line 1... at id(marketplace) =

I don't see why marketplace is not defined

4
I'm rather confused about your query. You match from marketplace to its products...but you never use the products in that marketplace. Instead, you have an alternate match to product, which is matching to every product with a ProductFeed. Basically your marketplace match isn't doing anything in your query at all. Didn't you want to work with products within a particular marketplace? Because your query isn't doing that. - InverseFalcon
Thats a good point. I am making a query builder that resulted in the above query, and I do have only one marketplace in my project right now, so I overlooked at that issue. Thank you for pointing out, i will try to fix that! - Dimitrios Kontoulis

4 Answers

1
votes

marketplace is not defined as variable, you should pass it in the WITH clause

MATCH (marketplace:`Marketplace`), 
(marketplace)-[rel_has_product_products:HAS_PRODUCT]->(products:`Product`),
 (product:`Product`), 
(product)-[rel_has_product_feed_productFeed:HAS_PRODUCT_FEED]->(productFeed:`ProductFeed`) 
WITH product, marketplace, 
count(productFeed) AS productFeed_count
 WHERE id(marketplace) = 123481 
and productFeed_count >= 1 
RETURN product 
1
votes

You have only taken product in WITH clause. marketplace should also be taken to further process.

Modified query

MATCH (marketplace:`Marketplace`), 
(marketplace)-[rel_has_product_products:HAS_PRODUCT]->(products:`Product`),
 (product:`Product`), 
(product)-[rel_has_product_feed_productFeed:HAS_PRODUCT_FEED]->(productFeed:`ProductFeed`) 
WITH product, marketplace,
count(productFeed) AS productFeed_count
 WHERE id(marketplace) = 123481 
and productFeed_count >= 1 
RETURN product 
1
votes

The problem here is that you're using a WITH clause to connect different sub queries. Only variables that are explicitly stated in the WITH clause are carried forward to the next clause.

MATCH (marketplace:`Marketplace`) ...
WITH product, count(productFeed) AS productFeed_count
WHERE id(marketplace) = 123481 and productFeed_count >= 1 
RETURN product 

You're not carrying marketplace into the WITH clause. So the correct way would be to either add the WHERE condition to the initial MATCH or carry marketplace into the WITHclause:

MATCH (marketplace:`Marketplace`), 
    (marketplace)-[rel_has_product_products:HAS_PRODUCT]->(products:`Product`),
    (product:`Product`), 
    (product)-[rel_has_product_feed_productFeed:HAS_PRODUCT_FEED]->(productFeed:`ProductFeed`) 
WHERE id(marketplace) = 123481 
WITH product, count(productFeed) AS productFeed_count
WHERE productFeed_count >= 1 
RETURN product

or

MATCH (marketplace:`Marketplace`), 
    (marketplace)-[rel_has_product_products:HAS_PRODUCT]->(products:`Product`),
    (product:`Product`), 
    (product)-[rel_has_product_feed_productFeed:HAS_PRODUCT_FEED]->(productFeed:`ProductFeed`) 
WITH marketplace, product, count(productFeed) AS productFeed_count
WHERE id(marketplace) = 123481 AND productFeed_count >= 1 
RETURN product

It seems as if option (1) would be the better way from a performance perspective as it eliminates unneeded paths (those not starting a marketplace 123481) very early in the process.

1
votes

While everyone else is correct that the fix for the problem in your question is to include marketplace in your WITH clause to keep it in scope, there's a more serious problem with your query that's being overlooked.

You have a match from a marketplace to products:Products, but you never actually use the products variable again in the entire query. Instead, you have a separate match to a new product variable that's matching to all :Products. You aren't constraining the products you're working with to a particular marketplace at all.

So let's fix this. There are also a number of other improvements to make:

  1. We should also make sure we constrain marketplace to the marketplace you want early, not at the end.
  2. We can get rid of any variables you aren't going to use, so let's ditch the relationship variables.
  3. You seem to only be matching from a product to its product feed for the sole purpose of making sure it has a product feed. We can do this easier and sooner by making this part of the WHERE clause on the first MATCH, making sure the products we match on have a product feed.

All of this makes for much more concise and efficient query.

MATCH (marketplace:`Marketplace`)-[:HAS_PRODUCT]->(product:`Product`)
WHERE id(marketplace) = 123481 AND (product)-[:HAS_PRODUCT_FEED]->(:`ProductFeed`)
RETURN product