Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
05-11-2020 01:45 AM
Guys, I am new to Neo4j platform and pretty much noob in writing cypher queries. I have a query which creates a brand, branches and checkoutTypes associated with it.
CREATE (brand:Brand {
id: apoc.create.uuid(),
name: $name,
logoUrl: $logoUrl,
coverUrl: $coverUrl,
tax: $tax,
deliveryCharges: $deliveryCharges,
category: $category,
isAvailable: $isAvailable,
color: $color
})
WITH brand
UNWIND $checkoutTypes as type
CREATE (checkoutType: FoodCheckoutType {
id: apoc.create.uuid(),
name: type.name
})
CREATE (coupon:FoodCoupon {
id: apoc.create.uuid(),
name: type.couponName,
percentage: type.percentage
}) - [:IN_CHECKOUT_TYPE] -> (checkoutType)
CREATE (checkoutType)-[:IN_BRAND]->(brand)
WITH brand
UNWIND $branches as branch
CREATE (foodBranch:FoodBranch {
id: apoc.create.uuid(),
name: branch.name,
phoneNumber: branch.phoneNumber,
latitude: branch.latitude,
longitude: branch.longitude,
preparationTime: branch.preparationTime,
isAvailable: branch.isAvailable
})
CREATE (foodBranch) -[:BRANCH_OF] -> (brand)
RETURN brand
and variables are
name: "Dominos",
logoUrl: "https://cdn.worldvectorlogo.com/logos/domino-s-pizza-3.svg",
coverUrl: "https://scontent.fbom3-1.fna.fbcdn.net/v/t1.0-",
branch: [
{
name: "Dominos Panchpakhadi",
phoneNumber: "2225437858",
latitude: 19.1796965,
longitude: 72.9562069,
isAvailable: true,
preparationTime: 2000
},
{
name: "Domino's , Mulund East",
phoneNumber: "18602100000",
latitude: 19.1724069,
longitude: 72.9580359,
isAvailable: true,
preparationTime: 2000
},
{
name: "Domino's ,Vasant Oscar ,Mulund West",
phoneNumber: "02225907250"
latitude: 19.1758063,
longitude: 72.9329858,
isAvailable: true,
preparationTime: 2000
}
]
checkoutTypes: [
{
name: "FastFood",
couponName: "25% off on all pizza",
percentage: 25
},
{
name: "Delivery",
couponName: "25% off on all pizza",
percentage: 25
},
{ name: "Takeaway",
couponName: "25% off on all pizza",
percentage: 25
}
]
But when I execute the query it creates multiple instances of the same branch which I don't want .
Is there any other way to refractor this Cypher query so its gives a desired results
Query Results are
{
"id": "dbb3414b-2928-4cd2-a708-c4ed1de7fc0c",
"name": "Dominos",
"checkoutType": [
{
"name": "FastFood",
"coupon": [
{
"name": "25% off on all pizza"
}
]
},
{
"name": "Takeaway",
"coupon": [
{
"name": "25% off on all pizza"
}
]
},
{
"name": "Delivery",
"coupon": [
{
"name": "25% off on all pizza"
}
]
}
],
"foodBranch": [
{
"name": "Domino's ,Vasant Oscar ,Mulund West",
"id": "3e88460d-c8ca-43c1-bb41-d0fbe44c40bd"
},
{
"name": "Domino's ,Vasant Oscar ,Mulund West",
"id": "abce0608-f49f-49d9-9acc-83c3c1bc9f6f"
},
{
"name": "Dominos Panchpakhadi",
"id": "f60ac181-10d8-4a62-9ddc-a076c91dbdd0"
},
{
"name": "Domino's , Mulund East",
"id": "aa2d8e36-b9bb-4b0d-9597-8c25c83df90f"
},
{
"name": "Domino's ,Vasant Oscar ,Mulund West",
"id": "76462ce9-f380-44ed-b6ca-6020e953c30e"
},
{
"name": "Domino's , Mulund East",
"id": "ec8022f9-0e61-4ac0-87f3-9e88a8570c65"
},
{
"name": "Domino's , Mulund East",
"id": "0b0075d5-5358-496d-8036-867ebce070f3"
},
{
"name": "Dominos Panchpakhadi",
"id": "f7fd7767-55f4-4a35-9780-cc1c0ab78f1b"
},
{
"name": "Dominos Panchpakhadi",
"id": "db50c866-6f54-418c-884a-54784b20a399"
}
]
}
Solved! Go to Solution.
05-18-2020 07:32 AM
This was mentioned earlier in my solution post, but here's the relevant section:
In cases where you need to use UNWIND, but later want to collapse the cardinality, you'll need to use either the DISTINCT keyword or usage of aggregation functions to get back to the state you want.
For example, in your query, once you're done with the operations for that particular UNWIND, you want to get back to distinct brands (and not multiple rows with the same brand).
So instead of WITH brand, you need either WITH DISTINCT brand or WITH brand, count(brand) as count (an aggregation function that would make brand distinct).
MATCH(brand: Brand { id: $brandId })
CREATE(product: FoodProduct {
id: apoc.create.uuid(),
name: $name,
isAvailable: $isAvailable,
coverUrl: $coverUrl,
category: $category,
isVeg: $isVeg,
description: $description
}) - [: PRODUCT_OF] - (brand)
WITH product
UNWIND $checkoutTypes as checkoutType
MATCH(checkout: CheckoutType { id: checkoutType })
CREATE(product) - [: HAS_CHECKOUT_TYPE] - (checkout)
WITH DISTINCT product // this resets the cardinality to 1 row per product
UNWIND $branches as branchId
MATCH(branch: FoodBranch { id: branchId })
CREATE(branch) - [: HAS_PRODUCT] - (product)
RETURN DISTINCT product // reset cardinality again
05-11-2020 04:42 AM
If the operations you want to use based on the list elements are only for writing (CREATE, MERGE, DELETE, SET, REMOVE), then use a FOREACH instead of an UNWIND. FOREACH won't alter the cardinality, so you can do two FOREACHes back to back.
05-11-2020 04:49 AM
Thanks for the reply, just a doubt when should I use UNWIND, is there any particular scenario ?
05-11-2020 04:55 AM
Either when you're faced with a limitation where you can't use FOREACH, or when you want to continue working with the resulting rows further in the query.
FOREACH does not allow non-writing clauses, so MATCH, OPTIONAL MATCH, and WITH are not allowed.
In cases where you need to use UNWIND, but later want to collapse the cardinality, you'll need to use either the DISTINCT keyword or usage of aggregation functions to get back to the state you want.
For example, in your query, once you're done with the operations for that particular UNWIND, you want to get back to distinct brands (and not multiple rows with the same brand).
So instead of WITH brand
, you need either WITH DISTINCT brand
or WITH brand, count(brand) as count
(an aggregation function that would make brand
distinct).
05-17-2020 12:00 AM
@andrew.bowman, Now I have this use case where I have to match IDs in an array and return it, but
now second UNWIND executes inside the first UNWIND which is not required.
Is there any way to stop the first UNWIND ? Or is there any other way to perform this query ?
MATCH (brand:Brand {id: $brandId})
WITH brand
UNWIND $checkoutTypes as checkoutType
MATCH (checkout: FoodCheckoutType {id: checkoutType})-[:IN_BRAND]-(brand)
WITH checkout, brand
UNWIND $branches as branchId
MATCH (branch: FoodBranch {id: branchId})
RETURN brand, checkout, branch
05-17-2020 09:24 AM
I'm a little confused with this query. You're not doing anything with the $braches or the resulting matched branches except matching and returning, it has nothing to do with the operations earlier in the query.
Can you describe what the intent of the query is, and what the desired results and format is supposed to be?
05-17-2020 09:06 PM
Purpose of the query is to validate IDs which are provide as variables.
Variables are as follows:
checkout = [1, 2 , 3],
branches = [1, 2, 3],
brand = 1
My purpose of the creating this query is check if this variables exists in the graph and return it.
But I have many other use cases where I have to MATCH and CREATE relationship and nodes inside the UNWIND. In that case I can't use FOREACH because it throws error for MATCH For eg:
MATCH(brand: Brand { id: $brandId })
CREATE(product: FoodProduct {
id: apoc.create.uuid(),
name: $name,
isAvailable: $isAvailable,
coverUrl: $coverUrl,
category: $category,
isVeg: $isVeg,
description: $description
}) - [: PRODUCT_OF] - (brand)
WITH product
UNWIND $checkoutTypes as checkoutType
MATCH(checkout: CheckoutType { id: checkoutType })
CREATE(product) - [: HAS_CHECKOUT_TYPE] - (checkout)
UNWIND $branches as branchId
MATCH(branch: FoodBranch { id: branchId })
CREATE(branch) - [: HAS_PRODUCT] - (product)
RETURN product
This query will create many duplicates branches relationship with products. I can't use MERGE because that would create relationship even if the branchId is not available and it will run several times.
Problem of the both query is same I can't use Consecutive Unwind statements with MATCH and CREATE in it because it will be create duplicates because of the nesting of the UNWIND, which is not desired. So how can I loop or UNWIND over two arrays consecutively but not nesting each other.
05-18-2020 07:32 AM
This was mentioned earlier in my solution post, but here's the relevant section:
In cases where you need to use UNWIND, but later want to collapse the cardinality, you'll need to use either the DISTINCT keyword or usage of aggregation functions to get back to the state you want.
For example, in your query, once you're done with the operations for that particular UNWIND, you want to get back to distinct brands (and not multiple rows with the same brand).
So instead of WITH brand, you need either WITH DISTINCT brand or WITH brand, count(brand) as count (an aggregation function that would make brand distinct).
MATCH(brand: Brand { id: $brandId })
CREATE(product: FoodProduct {
id: apoc.create.uuid(),
name: $name,
isAvailable: $isAvailable,
coverUrl: $coverUrl,
category: $category,
isVeg: $isVeg,
description: $description
}) - [: PRODUCT_OF] - (brand)
WITH product
UNWIND $checkoutTypes as checkoutType
MATCH(checkout: CheckoutType { id: checkoutType })
CREATE(product) - [: HAS_CHECKOUT_TYPE] - (checkout)
WITH DISTINCT product // this resets the cardinality to 1 row per product
UNWIND $branches as branchId
MATCH(branch: FoodBranch { id: branchId })
CREATE(branch) - [: HAS_PRODUCT] - (product)
RETURN DISTINCT product // reset cardinality again
All the sessions of the conference are now available online