كيفية جعل إنشاء عمل فريد من نوعه مع استعلام فرعي?

StackOverflow https://stackoverflow.com//questions/20002740

  •  20-12-2019
  •  | 
  •  

سؤال

لدي استعلام مثل هذا:

MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
  LIMIT 1 
RETURN left, right 
UNION MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
  SKIP 4 LIMIT 1 
RETURN left, right 
UNION MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
  SKIP 8 LIMIT 1 
RETURN left, right
CREATE UNIQUE left-[rel:FRIEND]->right 
RETURN rel;

بشكل عام ، أقوم فقط بإنشاء مجموعة بيانات حتى أتمكن من استخدامها لاحقا في إنشاء تعليمات فريدة.
من الواضح أن هذا لا يعمل - يقول محلل الاستعلام أنه لا يمكنني استخدام شرط الإرجاع إلا مرة واحدة.سؤالي هو-كيفية إنشاء مجموعة بيانات في هذه الحالة?حاولت تعيين اسم مستعار واستخدامه في إنشاء فريدة من نوعها - لا يمكن الحصول عليها للعمل إما.ماذا أفعل خطأ?هل هذا السيناريو ممكن حتى?

هل كانت مفيدة؟

المحلول

أنا قد يسيئون فهم ما كنت بعد ، ولكن هنا ما يحدث لي عندما أنظر إلى الاستعلام الخاص بك.

لتبدأ هنا هو التكيف من الاستعلام الخاص بك الذي يستخدم SKIP و LIMIT بدون RETURN أو UNION.

MATCH left, right
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6]
WITH left, right 
    LIMIT 1
CREATE UNIQUE left-[rel:FRIEND]->right
WITH [rel] as rels  //If you want to return the relationship later you can put it in a collection and bring it WITH
MATCH left, right
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6]
WITH left, right, rels 
    SKIP 4 LIMIT 1
CREATE UNIQUE left-[rel:FRIEND]->right
WITH rels + [rel] as rels
MATCH left, right
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6]
WITH left, right, rels 
    SKIP 8 LIMIT 1
CREATE UNIQUE left-[rel:FRIEND]->right
WITH rels + [rel] as rels
RETURN LENGTH(rels), rels  // You can return the relationships here but SKIP/LIMIT does its job also if you don't return anything

ولكن هذا الاستعلام هو البرية قليلا.انها حقا ثلاثة استعلامات ، حيث تم ضغط اثنين بشكل مصطنع في الاستعلامات الفرعية من الأول.يطابق نفس العقد من جديد في كل استعلام فرعي ، ولا يوجد أي شيء يتم اكتسابه عن طريق تشغيل الاستعلامات بهذه الطريقة وليس بشكل منفصل (إنه في الواقع أبطأ ، لأنه في كل استعلام فرعي تتطابق أيضا مع العقد التي تعرف أنك لن تستخدمها).

لذا فإن اقتراحي الأول هو استخدام START بدلا من MATCH...WHERE عند الحصول على العقد عن طريق معرف.كما هو عليه ، الاستعلام يربط كل عقدة في قاعدة البيانات باسم "اليسار" ، ثم كل عقدة في قاعدة البيانات باسم "الحق" ، ومن ثم تصفية جميع العقد ملزمة إلى "اليسار" التي لا تناسب الشرط في WHERE شرط ، ثم نفس الشيء ل "حق".نظرا لتكرار هذا الجزء من الاستعلام ثلاث مرات ، يتم ربط جميع العقد في قاعدة البيانات بإجمالي ست مرات.هذا مكلف لإنشاء ثلاث علاقات.إذا كنت تستخدم START يمكنك ربط العقد التي تريدها على الفور.هذا لا يجيب حقا على سؤالك ، لكنه سيكون أسرع وسيكون الاستعلام أنظف.لذلك ، استخدم START للحصول على العقد من خلال معرفهم الداخلي.

START left = node(1,2,3), right = node(4,5,6)

الشيء الثاني الذي أفكر فيه هو الفرق بين العقد و 'المسارات' أو 'عناصر النتيجة' عند مطابقة الأنماط.عند ربط ثلاث عقد في" اليسار "وثلاث عقد أخرى في" اليمين " ، ليس لديك ثلاثة عناصر نتيجة ، ولكن تسعة.لكل عقدة ملزمة في " اليسار "تحصل على ثلاث نتائج ، لأن هناك ثلاثة ممكن" الحق " لدمجها مع.إذا أردت ربط كل " يسار "بكل" يمين " ، فهذا رائع.لكنني أعتقد أن ما تبحث عنه هو عناصر النتيجة (1),(4), (2),(5), (3),(6), ، وعلى الرغم من أنه يبدو مناسبا لربط العقد الثلاثة "اليسرى" والعقد الثلاثة "اليمنى" في استعلام واحد مع مجموعات من معرفات العقدة ، عليك بعد ذلك القيام بكل هذه التصفية للتخلص من 6 مباريات غير مرغوب فيها.يصبح الاستعلام معقدا ومرهقا ، وهو في الواقع أبطأ من تشغيل الاستعلامات بشكل منفصل.طريقة أخرى لقول هذا هي أن تقول ذلك (1)-[:FRIEND]->(4) هو نمط متميز ، وليس (ذات الصلة) متصلة الأنماط الأخرى التي تقوم بإنشائها.سيكون الأمر مختلفا إذا أردت إنشاء (1)-[:FRIEND]->(2)<-[:FRIEND]-(3), ، ثم كنت ترغب في التعامل مع تلك العقد الثلاث معا.ربما كنت مجرد استكشاف استخدامات هامش سايفر ، ولكن اعتقدت أنني يجب أن نشير إلى ذلك.بالمناسبة ، باستخدام SKIP و LIMIT وبهذه الطريقة هو قليلا قبالة مفتاح ، انهم لا يقصد حقا لمطابقة نمط والتصفية.كما أنه لا يمكن التنبؤ به ، إلا إذا كنت تستخدم أيضا ORDER BY, ، حيث لا يوجد ضمان بأن النتائج ستكون بترتيب معين.أنت لا تعرف أي عنصر نتيجة يتم تمريره.على أي حال ، في هذه الحالة ، أعتقد أنه سيكون من الأفضل ربط العقد وإنشاء العلاقة في ثلاثة استعلامات منفصلة.

START left = node(1), right = node(4)
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

START left = node(2), right = node(5)
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

START left = node(3), right = node(6)
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

بما أنك تعرف بالفعل أنك تريد هذه الأزواج الثلاثة ، وليس ، على سبيل المثال, (1),(4),(1),(5),(1),(6) سيكون من المنطقي الاستعلام عن تلك الأزواج فقط ، وأسهل طريقة هي الاستعلام بشكل منفصل.

لكن ثالثا, ، نظرا لأن الاستعلامات الثلاثة متطابقة هيكليا ، وتختلف فقط في قيمة الخاصية (إذا كان المعرف يعتبر خاصية) ، يمكنك تبسيط الاستعلام عن طريق تعميم أو إخفاء الهوية التي تميزها ، أي.استخدام المعلمات.

START left = node({leftId}), right = node({rightId})
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

parameters: {leftId:1, rightId:4}, {leftId:2, rightId:5}, {leftId:3, rightId:6}

نظرا لأن الهيكل متطابق ، يمكن سايفر تخزين خطة التنفيذ مؤقتا.هذا يجعل الأداء جيدا ، والاستعلام مرتب وقابل للصيانة ويمكن تمديده بسهولة إذا كنت تريد لاحقا إجراء نفس العملية على أزواج أخرى من العقد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top