استعلام MongoDB يُرجع 0 عنصر عند التنفيذ الأول لكن ينجح عند التنفيذ الثاني

أشهد سلوكًا غريبًا جدًا في سير عمل n8n باستخدام MongoDB.
سير العمل هو:

  • يستقبل Webhook LeadUserID و property_id
  • تنسق عقدة Set البيانات
  • تجد عقدة MongoDB مستند Campaign حسب property_id
  • تبحث عقدة MongoDB الثانية في مجموعة Campaign_Members باستخدام:
    • Customer_ID من webhook
    • Campaign_ID (_id) من عقدة MongoDB السابقة
      المشكلة أن عقدة MongoDB الثانية تتصرف بشكل غير متسق:
  • تنفيذ سير العمل التلقائي → يرجع 0 عناصر
  • التنفيذ اليدوي الأول في المحرر → يرجع 0 عناصر
  • التنفيذ اليدوي الثاني (بدون تغيير أي شيء) → يرجع بنجاح المستند المطابق
    الاستعلام هو:
={
  "Customer_ID": "{{ $('Edit Fields').first().json.body.args.LeadUserID }}",
  "Campaign_ID": "{{ $json._id }}"
}

البيانات موجودة بالفعل في قاعدة البيانات، لذا هذا ليس شرطًا للسباق مع إدراج حديث.
ما يربكني هو أن لا شيء يتغير بين التنفيذ الأول والثاني، مع ذلك ينجح التنفيذ الثاني بشكل متسق.
هل واجه أحد سلوك “التنفيذ الأول فشل، التنفيذ الثاني ينجح” هذا مع عقد MongoDB؟ هل يمكن أن يكون مرتبطًا بأنواع البيانات (مثل ObjectId مقابل string)، أو توقيت تقييم التعبير، أو حالة التنفيذ، أو خصوصية أخرى خاصة بـ n8n؟

معلومات عن إعداد n8n الخاص بك

  • إصدار n8n: الإصدار الأحدث
  • قاعدة البيانات (الافتراضية: MongoDB):
  • إعداد EXECUTIONS_PROCESS في n8n (الافتراضي: own, main):
  • تشغيل n8n عبر: n8n cloud
  • نظام التشغيل:

مرحباً @alee_Ostovar

تحتاج إلى التأكد من تمرير Campaign_ID كـ ObjectId.

الطريقة الأكثر موثوقية للتعامل مع ObjectId في n8n هي إنشاء كائن الاستعلام في عقدة Code. يمنع هذا n8n من تحويل معرّفاتك إلى سلاسل نصية عن طريق الخطأ.

  1. أضف عقدة Code قبل عقدة MongoDB الثانية.
  2. استخدم هذا الكود:
const leadUserId = $('Edit Fields').first().json.body.args.LeadUserID;
const campaignId = $json._id;

return {
  query: {
    Customer_ID: leadUserId,
    Campaign_ID: { "$oid": campaignId } // يخبر هذا MongoDB بمعاملة المعرّف كـ ObjectId
  }
};
  1. في عقدة MongoDB، بدلاً من كتابة JSON يدويًا، استرجع مخرجات عقدة Code: {{ $json.query }}

@alee_Ostovar
واجهت مشكلة مشابهة جداً مع Postgres. مما تمكنت من التوصل إليه، كانت المشكلة تتعلق بالبيانات المثبتة في المشغل، خاصةً إذا كان المشغل عبارة عن webhook أو مشغل “عند تنفيذه بواسطة سير عمل آخر”. على الرغم من أنه لا يُفترض حدوث ذلك، كانت البيانات المثبتة من المشغل يتم تمريرها إلى المراحل اللاحقة أثناء عمليات الإنتاج، وأحياناً تكون هذه البيانات خاطئة أو مجرد قيمة فارغة من الاختبار اليدوي. وبعد ذلك عندما تفتح يدويًا التنفيذ الذي فشل - تُستبدل البيانات المثبتة للمشغل وتعمل بسحر.

تمكنت من حل المشكلة بالتأكد من إلغاء تثبيت بيانات المشغل دائماً قبل أن ينطلق سير العمل الخاص بي. لم تحدث منذ ذلك الحين، وكانت تحدث في السابق بنسبة 50% تقريباً من الوقت. أتمنى أن يكون هذا مفيداً.

شكرًا على الاقتراح. في حالتي، Campaign_ID لم يتم تخزينه كـ MongoDB ObjectId. تم تخزينه كـ سلسلة نصية في مجموعة Campaign_Members (إنها مجرد قيمة مرجعية، وليست حقل ObjectId فعلي).

بسبب ذلك، تغليفه كـ { "$oid": campaignId } سيجعل الاستعلام يبحث عن ObjectId، وهو لن يتطابق مع قيمة السلسلة النصية المخزنة.

هذا هو السبب في

هذا يرجع إلى عدم تطابق نوع البيانات

شكراً، لقد جربت ذلك بالفعل. تأكدت من أن مشغل Webhook لم يكن مثبتاً، لكن للأسف السلوك لم يتغير.

أحد الحلول البديلة التي وجدتها هو استبدال عقدة Edit Fields (Set) بعقدة Code تنشئ نفس المخرجات. مع عقدة Code، يعمل سير العمل بشكل صحيح في كل مرة.

لاحظت أيضاً مشكلة أخرى يبدو أنها مرتبطة بعقدة Edit Fields: عند تمرير مستندات MongoDB من خلالها، قد يتم تحويل معرّف MongoDB _id أحياناً إلى Buffer بدلاً من البقاء في شكله الأصلي. يبدو أن هذه مشكلة منفصلة في عقدة Set/Edit Fields نفسها.

في الوقت الحالي، يعمل استخدام عقدة Code كحل بديل لكلتا المشكلتين، لكنه يشعر أكثر بأنني أتجنب الخلل بدلاً من إصلاحه. أحاول فهم السبب وراء تصرف عقدة Set/Edit Fields الأصلية بهذه الطريقة.

لا أعتقد أن هذا خطأ عدم تطابق نوع البيانات، لأن كلا variables يتم تخزينهما كنصوص، والاستعلام يستخدم أيضًا قيم نصية. إذا كان هناك عدم تطابق في النوع، فقد أتوقع أن يفشل بشكل متسق بدلاً من الفشل في التنفيذ الأول فقط.

تمكنت من حل المشكلة بدلاً من استبدال عقدة Edit Fields (Set) بعقدة Code. هذا يعمل، لكنني أحاول فهم سبب ظهور عقدة Set الأصلية لهذا السلوك في المقام الأول.

في MongoDB، حقل _id ليس نصاً (string)؛ بل هو نوع BSON خاص يُسمى ObjectId.

في استعلامك:

{
  "Customer_ID": "{{ $('Edit Fields').first().json.body.args.LeadUserID }}",
  "Campaign_ID": "{{ $json._id }}"
}

بإحاطة {{ $json._id }} بعلامات الاقتباس المزدوجة، تخبر n8n بشكل صريح بمعاملة Campaign_ID كـ نص (string). عندما يستقبل MongoDB نصاً لحقل مخزّن كـ ObjectId، يُرجع صفراً من النتائج لأن النص لا يساوي ObjectId، حتى لو كانت الأحرف متطابقة.

أثناء التنفيذ اليدوي الأول، قد تفشل العقدة في حل التعبير بالطريقة المتوقعة تماماً أو تفشل استعلام قاعدة البيانات. ومع ذلك، أثناء التنفيذ الثاني، يستخدم المحرر غالباً المخرجات المخزنة مؤقتاً من حالة تنفيذ العقدة السابقة.

هل ينطبق هذا على حالتك؟

هذا هو الجزء الذي يسبب الالتباس بالفعل، وهو في الواقع المشكلة الثانية التي واجهتها.

عقدة Edit Fields تمرر أحيانًا _id باسم [object Object]، لذلك اشتبهت بأنها مشكلة نوع بيانات. للتحقق، قمت بتسجيل القيمة باستخدام عقدة Code مباشرة بعد عقدة MongoDB (قبل تحرير الحقول). إليك الناتج:

[
  {
    "value": "6a579e9014256aa1f68ca592",
    "typeof": "string",
    "constructor": "String",
    "isObject": false,
    "proto": "Object"
  }
]

ظاهريًا، تبدو وكأنها سلسلة نصية بدائية. ومع ذلك، بالنظر إلى السلوك الذي أراه، أشك في أنه قد يكون هناك غلاف BSON أساسي أو بعض النوع الداخلي/الوكيل المشارك الذي لا ينعكس في ناتج عقدة Code. وهذا يفسر السبب في أن عقدة MongoDB تتعامل لاحقًا مع القيمة كائن بدلاً من سلسلة نصية.

لفرض أن تكون سلسلة نصية بدائية في كل مرة (تلقائية أو يدوية)، يجب عليك تغليف التعبير الخاص بك في مُنشئ السلسلة النصية في JavaScript.

غيّر استعلامك من هذا:

{
  "Customer_ID": "{{ $('Edit Fields').first().json.body.args.LeadUserID }}",
  "Campaign_ID": "{{ $json._id }}"
}

إلى هذا:

{
  "Customer_ID": "{{ String($('Edit Fields').first().json.body.args.LeadUserID) }}",
  "Campaign_ID": "{{ String($json._id) }}"
}

بتغليف التعبير في String()، تفرض على محرك التعبيرات n8n تنفيذ عملية تحويل JavaScript قبل تمرير القيمة إلى عقدة MongoDB. هذا يزيل أي أغلفة BSON أو وكلاء أو بيانات تعريف الكائن، مما يضمن أن MongoDB يتلقى سلسلة نصية حرفية في كل مرة.