Учитывая следующую схему
Мне нужно получить список Collection
каждый с набором ProductCard
(это Product
вариант) критериев соответствия, указанных пользователем:
- тип коллекции
- 1..4 типов продукта (Для каждого выбранного
ProductType
должен быть один ProductCard
в наборе.)
- цена за комплект
Я начал с запроса, подобного этому
MATCH (c:Collection {type: 'selected_collection_type'})<-[:FROM_COLLECTION]-(:Product)-[:OF_TYPE]->(pt1:ProductType {title: '1st product type'}), (c)<-[:FROM_COLLECTION]-(:Product)-[:OF_TYPE]->(pt2:ProductType {title: '2nd product type'}),(c)<-[:FROM_COLLECTION]-(:Product)-[:OF_TYPE]->(pt3:ProductType {title: '3rd product type'}), (c)<-[:FROM_COLLECTION]-(:Product)-[:OF_TYPE]->(pt4:ProductType {title: '4th product type'})
CALL apoc.cypher.run('
WITH {c} AS c, {pt1} AS pt1, {pt2} AS pt2, {pt3} AS pt3, {pt4} AS pt4
MATCH (pt1)<-[:OF_TYPE]-(p1:Product)-[:FROM_COLLECTION]->(c), (pt2)<-[:OF_TYPE]-(p2:Product)-[:FROM_COLLECTION]->(c), (pt3)<-[:OF_TYPE]-(p3:Product)-[:FROM_COLLECTION]->(c), (pt4)<-[:OF_TYPE]-(p4:Product)-[:FROM_COLLECTION]->(c), (pc1:ProductCard)-[:VARIANT_OF]->(p1), (pc2:ProductCard)-[:VARIANT_OF]->(p2), (pc3:ProductCard)-[:VARIANT_OF]->(p3), (pc4:ProductCard)-[:VARIANT_OF]->(p4)
WHERE (pc1.price + pc2.price + pc3.price + pc4.price < price_margin_for_set)
RETURN pc1, pc2, pc3, pc4, (p1.weight + p2.weight + p3.weight + p4.weight) AS sweight ORDER BY sweight DESC LIMIT 1
', {c:c, pt1:pt1, pt2:pt2, pt3:pt3, pt4:pt4}) YIELD value
RETURN c, value ORDER BY value.sweight DESC LIMIT 8;
и он работает достаточно хорошо для 3 выбранных типов продуктов, но когда я добавляю 4-й тип продукта, все резко замедляется. Проблема здесь в том, что мне просто нужен 1 набор, возвращенный из подзапроса, но декартово произведение, вычисленное для всех вариантов продукта (Product
может иметь 1 .. ~ 10 ProductCard
), достаточно велико для 4 типов.
Как оптимизировать этот запрос для повышения производительности / уменьшить количество вариаций, необходимых для возврата 1 набора критериев соответствия цены из подзапроса?
Вот ОБЪЯСНИТЬ
1033 * объяснить *
EDIT:
немного изменил запрос
WITH ['Product Type 1', 'Product Type 2', 'Product Type 3', 'Product Type 4'] as types
MATCH (c:Collection)<-[:FROM_COLLECTION]-(:Product)-[:OF_TYPE]->(pt:ProductType)
WHERE pt.title in types AND c.type = 'collection type'
WITH c, size(types) as inputCnt, count(DISTINCT pt) as cnt
WHERE cnt = inputCnt
CALL apoc.cypher.run('
WITH {c} AS c
MATCH (c)<-[:FROM_COLLECTION]-(p1:Product)-[:OF_TYPE]->(:ProductType {title: "Product Type 1"})
MATCH (pc1:ProductCard)-[:VARIANT_OF]->(p1)
MATCH (c)<-[:FROM_COLLECTION]-(p2:Product)-[:OF_TYPE]->(:ProductType {title: "Product Type 2"})
MATCH (pc2:ProductCard)-[:VARIANT_OF]->(p2)
MATCH (c)<-[:FROM_COLLECTION]-(p3:Product)-[:OF_TYPE]->(:ProductType {title: "Product Type 3"})
MATCH (pc3:ProductCard)-[:VARIANT_OF]->(p3)
MATCH (c)<-[:FROM_COLLECTION]-(p4:Product)-[:OF_TYPE]->(:ProductType {title: "Product Type 4"})
MATCH (pc4:ProductCard)-[:VARIANT_OF]->(p4)
WHERE (pc1.price + pc2.price + pc3.price + pc4.price < 1000)
RETURN pc1, pc2, pc3, pc4, (p1.weight + p2.weight + p3.weight + p4.weight) AS sweight ORDER BY sweight DESC LIMIT 1
', {c:c}) YIELD value
RETURN DISTINCT c, value LIMIT 8;
Объясните
Объяснить подзапрос