Navvo
مرجع الواجهة البرمجية

البحث

بحث الأماكن في الأردن والمنطقة — استعلامات بالعربية والإنجليزية والعربيزي، وترتيب يتسامح مع الأخطاء الإملائية، ومرشّحات، وأوجه، وإبراز للمطابقات، ومطابقة اختيارية بالمعنى.

البحث

بحث نصّي حرّ في كتالوج الأماكن لدى Navvo. يتعامل مربّع استعلام واحد مع العربية والإنجليزية والعربيزي (العربية مكتوبةً بحروف لاتينية وأرقام، مثل saydaliyeh أو mat3am) والاستعلامات المختلطة. تتعرّف Navvo على كلمات التصنيفات (pharmacy، صيدلية) والمناطق (cafe in Abdoun) وعبارات «قريب مني» و«مفتوح الآن»، وتتسامح مع الأخطاء الإملائية، وترتّب النتائج بحسب مدى مطابقة اسم المكان أولًا قبل أن تزن المسافة والشعبية.

فهم الاستعلام حتميّ: هو مجموعة قواعد ومفردات منسَّقة، وليس نموذج ذكاء اصطناعي، لذا يُقرأ الاستعلام نفسه دائمًا بالطريقة نفسها ولا ينتظر نموذجًا أبدًا. ويعمل كل ذلك على البنية التحتية الخاصة بـ Navvo.

يشمل التسامح مع الأخطاء الإملائية الكلمات القصيرة أيضًا. خذ كلمة إنجليزية من أربعة إلى ستة أحرف لا يستخدمها أي اسم مكان، لكنها تختلف بحرف واحد عن كلمة تستخدمها أسماء الأماكن. تبحث Navvo أيضًا عن صيغتها المصحّحة إلى جانب الاستعلام كما كُتب، وترتّب مجموعتي النتائج معًا: cafr تجد المقاهي وhotl تجد الفنادق. يُستمدّ التصحيح من الكلمات الواردة في أسماء الأماكن لدى Navvo نفسها، ويفضّل أكثر أخطاء الكتابة شيوعًا، مثل مفتاح مجاور أو حرفين متبادلين. ولا تُصحَّح كلمات العربيزي بهذه الطريقة، لأنها عربية مكتوبة بحروف لاتينية وليست أخطاء إملائية.

النطاق المطلوب: search

نقطة النهايةاستخدمها لـ
GET /searchقائمة النتائج.
GET /search/suggestionsاقتراحات الإكمال التلقائي أثناء كتابة المستخدم.
GET /search/similar«المزيد من هذا النوع» في صفحة مكان.
POST /search/eventsالإبلاغ عن النتيجة التي فتحها المستخدم، بموافقته.
تحديث 2026-09-30. صار للبحث مسار معالجة جديد للاستعلامات. يحتفظ كل حقل موجود في الاستجابة باسمه ونوعه، وكل ما هو جديد إضافيّ. تغيّرت أربعة سلوكيات تستحق المراجعة في تكاملك:
  • صار locale يُحترَم ويُعاد صداه. كان يُسقَط سابقًا، فكانت كل استجابة تقول en.
  • صار lat/lon يخضعان لفحص المدى، والإحداثي الواقع خارج الكرة الأرضية يعيد 400. ويُقتطَع q عند 200 حرف.
  • يشمل category التصنيفات الفرعية: يعيد category=food-and-drink المقاهي والمطاعم والمخابز.
  • صار understanding يأتي من المحلّل الحتمي ومتاحًا دائمًا. أمّا محتواه القديم الذي كان يولّده نموذج فقد زال.
الترتيب الموصوف في هذه الصفحة مُفعَّل منذ 30 أيلول 2026، والمطابقة بالمعنى منذ 1 تشرين الأول 2026.السجلّات التي تحتفظ بها Navvo عند البحث وطريقة عمل الموافقة مشروحة في تحليلات البحث والخصوصية.

ابحث عن الأماكن باستعلام نصّي حر.

curl -s "https://navvo.io/api/v1/search?q=coffee&lat=31.9539&lon=35.9106&limit=10" \
  -H "x-api-key: nvvo_YOUR_KEY"

معاملات الاستعلام

q
string required
استعلام البحث كما كتبه المستخدم: coffee in Abdoun، صيدلية مناوبة قريبة، saydaliyeh، Abdali Mall. يجب ألّا يكون فارغًا. ويُتجاهَل ما يتجاوز 200 حرف.
locale
string
لغة المستخدم. أرسل en أو ar، أو وسم لغة كاملًا مثل ar-JO أو en-US (حتى 35 حرفًا). الوسوم التي تبدأ بـ ar تُحَلّ إلى ar وكل ما عداها إلى en، وتُعيد الاستجابة القيمة المُحلَّلة. لا يُصفّي locale النتائج أبدًا: تُطابَق الأسماء العربية والإنجليزية أيًّا كانت القيمة التي ترسلها.
page
number
رقم الصفحة بدءًا من 1. القيمة الافتراضية 1، والقيم الأصغر من 1 تُرفَع إلى 1.
limit
number
عدد العناصر في الصفحة. القيمة الافتراضية 25، مُقيَّدة إلى 1–100. تُقيَّد القيم الخارجة عن المدى ولا تُرفَض.
bbox
string
«ابحث في هذه المنطقة»: west,south,east,north. لا تُعاد إلا الأماكن الواقعة داخل الصندوق، وتُعيد الاستجابة bbox. تُتجاهَل القيمة المشوَّهة.
lat
number
خط عرض نقطة الأصل للترتيب، من −90 إلى 90. أرسله مع lon. تتقدّم الأماكن الأقرب ضمن نطاق المطابقة نفسه (انظر الترتيب)، لكن نقطة الأصل لا تُصفّي شيئًا إلا إذا أرسلت radiusKm أيضًا. تُعيد الاستجابة near: { lat, lng }. والقيمة غير الرقمية أو الخارجة عن المدى تعيد 400.
lon
number
خط طول نقطة الأصل للترتيب، من −180 إلى 180. يُقبل lng كاسم بديل، وإرسال الاثنين بقيمتين مختلفتين يعيد 400.
lng
number
اسم بديل لـ lon.
originType
string
طبيعة نقطة الأصل. device (الافتراضية) تعني موقع المستخدم نفسه. وmap تعني مركز الخريطة التي ينظر إليها: عندها يقلّ وزن المسافة ويتلاشى أثرها على نطاق أوسع، ولا تحمل العناصر distanceKm. أرسل map عندما توجّه بحثًا نصيًا عاديًا نحو ما يظهر على الشاشة لا نحو المستخدم.
category
string
لا تُعاد إلا الأماكن في هذا التصنيف أو في أيٍّ من تصنيفاته الفرعية. فـ category=food-and-drink يشمل المقاهي والمطاعم والمخابز، وcategory=pharmacy يشمل الصيدليات فقط. أرسل عدة معرّفات مفصولة بفواصل لمطابقة أيٍّ منها: category=cafe,coffee-shop (حتى 10). المعرّفات من GET /places/categories، والقيمة التي ليست تصنيفًا لا تطابق شيئًا. تُعيد الاستجابة category.
mode
string
submit (الافتراضية) لبحث طلبه المستخدم، بالضغط على Enter مثلًا. وtypeahead للطلبات المُرسَلة أثناء الكتابة: تُعدّ مطابقات البادئة قوية، ويزداد وزن الأماكن الشائعة (فالمستخدم غالبًا يكتب اسمًا معروفًا)، ولا تعمل المطابقة بالمعنى أبدًا. كما يُعلِم تحليلات Navvo بأيّ الطلبات كانت ضغطات مفاتيح.
semantic
string
المطابقة بالمعنى: auto (الافتراضية) أو on أو off. انظر المطابقة بالمعنى. مع مفتاح API تتصرّف auto مثل off، فأرسل on لتفعيلها.
facets
string
أسماء الأوجه المطلوب عدّها، مفصولة بفواصل: category أو amenities أو كلاهما. تُتجاهَل الأسماء غير المعروفة. انظر الأوجه.
highlight
boolean
عند true، تحمل العناصر التي يطابق اسمُها الاستعلامَ كائن highlight. انظر الإبراز.
openNow
boolean
عند true، لا تُعاد إلا الأماكن المفتوحة الآن. يُقيَّم ذلك بتوقيت الأردن مع مراعاة العطل الرسمية. وتُستبعَد الأماكن التي لا تتوفّر لها بيانات ساعات العمل.
minRating
number
فقط الأماكن التي تقييمها لا يقلّ عن هذه القيمة، من 0 إلى 5.
price
string
مستويات السعر المطلوبة مفصولة بفواصل (1,2): 1 حتى 5 دنانير للشخص، و2 من 5 إلى 10 دنانير، و3 من 10 إلى 20 دينارًا، و4 أكثر من ذلك. يطابق المكان إذا وقع منتصف نطاق سعره المُدرَج، بعد تحويله إلى الدينار، ضمن أحد هذه المستويات. تُستبعد الأماكن التي لا يُدرَج لها سعر، ولا يُدرَج السعر إلا لبضعة آلاف من الأماكن (معظمها مقاهٍ ومطاعم)، لذا يعيد مرشّح السعر نتائج أقل بكثير.
sort
string
relevance (الافتراضية)، أو distance (الأقرب أولًا، ويتطلّب lat/lon)، أو rating (الأعلى تقييمًا أولًا). يحلّ distance وrating محلّ ترتيب الصلة كليًّا.
radiusKm
number
فقط الأماكن الواقعة ضمن هذا العدد من الكيلومترات حول lat/lon، من 0.1 إلى 500. يتطلّب نقطة أصل.
amenities
string
معرّفات سمات مفصولة بفواصل. لا يُطابَق المكان إلا إذا امتلكها كلها، مثل wheelchair-accessible-entrance,delivery. هي معرّفات الخيارات نفسها في GET /places/facets ← options[].slug، أو يمكنك أخذها من facets=amenities.
analytics
boolean
أرسل false فلا تحتفظ تحليلات البحث لدى Navvo بأي سجلّ لهذا البحث. هو مماثل لترويسة X-Navvo-Analytics: off، والإعداد المناسب للاختبارات وفحوص الجاهزية والمهام المجمَّعة.
المعاملات المنطقية (highlight، openNow، analytics) تقرأ true أو 1 على أنها صحيحة. وأي قيمة أخرى، بما فيها false و0 وyes، تُعدّ خاطئة. ولأن analytics مفعَّل افتراضيًا، فأي قيمة غير true/1 تُعطّله.

ترويسات الطلب

هذه الترويسات كلها اختيارية. الأربع الأولى تتحكّم فيما تسجّله Navvo، وتشرح صفحة تحليلات البحث والخصوصية النموذج الذي تقوم عليه.

X-Navvo-Session
string
معرّف عشوائي لجلسة المستخدم الحالية، تولّده أنت وترسله فقط بعد موافقة المستخدم على أن يُسهم نشاطه في تحسين البحث. به يمكن ربط النقرات التي تُبلغ عنها عبر POST /search/events بهذا البحث، وتُحتسب سلسلة البحث أثناء الكتابة بحثًا واحدًا. الصيغة: من 16 إلى 64 حرفًا من A–Z a–z 0–9 _ -، دون ستة أرقام متتالية أو أكثر. وتُتجاهَل أي قيمة أخرى. لا تشتقّه أبدًا من معرّف مستخدم أو بريد إلكتروني أو رقم هاتف أو معرّف جهاز. لا تخزّن Navvo إلا تجزئة مُفتاحية له تُحسَب مع التاريخ، فلا يمكن ربط تجزئات الأيام المختلفة بعضها ببعض.
X-Navvo-Analytics
string
off تُبقي هذا البحث خارج تحليلات البحث لدى Navvo، تمامًا مثل analytics=false.
Sec-GPC
string
1 تعني أن متصفّح المستخدم يطلب عدم التتبّع (Global Privacy Control). عندها تتجاهل Navvo X-Navvo-Session وترفض الأحداث الخاصة بهذا البحث. ويبقى سجلّ البحث محفوظًا، لكن دون ربطه بجلسة.
DNT
string
تُعامَل 1 تمامًا مثل Sec-GPC: 1. إذا كنت تمرّر عمليات البحث عبر خادمك، فمرّر الترويستين كلتيهما من طلب المستخدم.
X-Navvo-Source
string
وسم اختياري لنوع الحركة. sdk يميّز الطلبات الصادرة عن حزمة تطوير (SDK) مبنية على Navvo، والقيم الأخرى محجوزة لتطبيقات Navvo نفسها. تُصنَّف طلبات مفاتيح API التي لا تحمل sdk على أنها api. وتُرسل حزم Navvo نفسها القيمة sdk تلقائيًا: حزمتا الويب و Node ابتداءً من 0.2.1، وحزم Python و Go و Java ابتداءً من 0.2.0. وإذا كانت حزمة الويب تصل إلى الواجهة البرمجية عبر خادم وسيط خاص بك، فاسمح بترويسة الطلب هذه في سياسة CORS لديه.

الاستجابة

الحقلالنوعالوصف
querystringاستعلامك، يُعاد صداه.
localestringاللغة المُحلَّلة: en أو ar.
queryIdstringمعرّف من 24 حرفًا لقائمة النتائج هذه. مرّره إلى POST /search/events عندما يفتح المستخدم نتيجة. وهو معرّف معتم: لا يحتوي على نص الاستعلام ولا على بيانات المستخدم، ويُصدَر معرّف جديد مع كل طلب.
understandingobjectكيف قُرئ الاستعلام. انظر فهم الاستعلام.
places.items[]arrayالنتائج المرتَّبة (انظر أدناه). تكون فارغة عند عدم وجود تطابق: لا تحشو Navvo القائمة أبدًا بأماكن غير ذات صلة.
places.totalnumberعدد الأماكن المطابقة. على الفهرس هو تقدير سقفه 1,000، فتعامل معه على أنه «نحو N نتيجة». ولا يكون 0 إلا عند انعدام التطابق فعلًا.
places.page / places.limitnumberصدى ترقيم الصفحات.
facetsobjectفقط عند طلب facets. انظر الأوجه.
suggestions[]arrayفقط عندما تكون places.items فارغة: أماكن شائعة قرب نقطة الأصل تعرضها كبديل «لا نتائج — جرّب هذه». بنفس بنية places.items[]. انظر عند عدم وجود نتائج.
didYouMeanstringفقط عند انعدام التطابق في استعلام يبدو خطأً إملائيًا: استعلام مُصحَّح مأخوذ من المفردات المعتمدة لدى Navvo. نص عادي.
bbox / category / near—صدى bbox وcategory ونقطة الأصل التي أرسلتها.
indexobjectحالة فهرس البحث: { provider, configured, available, mode }. انظر حالة الفهرس والمراقبة.

تحمل كل استجابة الترويسة Cache-Control: no-store. لكل استجابة queryId جديد، فالنسخة المخزَّنة مؤقتًا قد تربط نقرات المستخدم ببحث شخص آخر. لا تخزّن استجابات /search مؤقتًا في Service Worker ولا في شبكة توصيل محتوى.

كل عنصر من عناصر places.items[]:

الحقلالنوعالوصف
idstringمعرّف المكان.
slugstringمعرّف الرابط، يُستخدم مع GET /places/{slug}.
nameEn / nameArstring | nullالأسماء.
nameEnTransliteratedbooleanيظهر بقيمة true فقط عندما يكون nameEn ناتجًا عن كتابة الاسم العربي بحروف لاتينية لعدم معرفة اسم إنجليزي (نحو 35,000 مكان). اعرض nameAr أولًا لهذه الأماكن، ولا تقدّم nameEn على أنه اسم رسمي.
categoriesstringمعرّفات التصنيفات القياسية، والتصنيف الأساسي أولًا.
canonicalCategorySlugstring | nullالتصنيف الأساسي.
rawCategoriesstringالتصنيفات الأصلية غير المُطبَّعة.
ratingnumberالتقييم، أو 0 إن لم يوجد.
sponsoredbooleanإدراج مُموَّل، أو موضع مدفوع وضعته قاعدة من Navvo.
promotedbooleanيظهر بقيمة true فقط عندما تضع قاعدة تحريرية أو ممولة من Navvo هذه النتيجة. ميّزها في واجهتك (مثلًا «مُروَّج»).
centerstringالموقع بصيغة WKT على شكل POINT(<lng> <lat>)، خط الطول أولًا.
lat / lngnumber | nullالإحداثيات نفسها كأرقام، أو null عندما يكون center مفقودًا.
iconLightUrl / iconDarkUrlstring | nullأيقونات دبوس التصنيف، كروابط مطلقة. انظر الأماكن ← أيقونات تصنيف الأماكن.
imageUrlstring | nullصورة المكان كرابط مطلق، أو null عند عدم وجودها. انظر الأماكن ← صورة المكان.
distanceKmnumberالمسافة المستقيمة عن lat/lon بالكيلومترات. تظهر فقط مع نقطة أصل من نوع الجهاز (originType=device، الافتراضية).
highlightobjectمع highlight=true: { nameEn?, nameAr? }. انظر الإبراز.
reviewCountnumberعدد المراجعات التي يستند إليها rating. يظهر عند توفّره.
categoryNamestringاسم الفئة الرئيسية للعرض بلغة locale في الاستجابة، مثل Coffee Shop أو مقهى.
priceRangestringالإنفاق المعتاد للشخص كما هو مُدرَج، مثل JOD 5–10. يظهر عند توفّره.
priceLevelnumberمن 1 إلى 4: المستوى الذي يرشّح عليه price، ويُحسب من priceRange (مثل $ إلى $$$$). يظهر عندما يمكن قراءة priceRange.
addressstringعنوان شارع قصير يُعرض في سطر واحد، بخط لغة locale في الاستجابة إن وُجد للمكان، مثل Al-Mutanabbi St. 22.
areastringالحي أو المنطقة، مثل Zahran.
hoursobjectحالة الدوام اليوم بتوقيت الأردن. انظر تفاصيل النتيجة. يغيب إذا لم تكن للمكان ساعات عمل.
highlightsstringحتى ثلاثة أشياء يُعرف بها المكان، مثل Great coffee أو Rooftop seating. بالإنجليزية.
{
  "query": "coffee",
  "locale": "en",
  "queryId": "AaDxmIYgiEC1I4ZdHCWiERmR",
  "understanding": {
    "unavailable": false,
    "purpose": "search_understanding",
    "parsed": { "language": "en", "intent": "place", "category": "Coffee Shop", "categories": ["coffee-shop", "cafe", "coffee-stand", "cafeteria", "cat-cafe", "tea-house"] }
  },
  "places": {
    "items": [
      {
        "id": "e3bacbd9-1e5d-474c-b84e-2fe7e1556541",
        "slug": "coffee-factory-co-jabal-amman-a3ddbd",
        "nameEn": "Coffee Factory & Co. - Jabal Amman",
        "nameAr": null,
        "categories": ["coffee-shop"],
        "canonicalCategorySlug": "coffee-shop",
        "rawCategories": ["Coffee shop"],
        "rating": 4.6,
        "sponsored": false,
        "center": "POINT(35.905152 31.952061)",
        "lat": 31.952061,
        "lng": 35.905152,
        "iconLightUrl": "https://navvo.io/uploads/category-icons/coffee-shop-light.svg",
        "iconDarkUrl": "https://navvo.io/uploads/category-icons/coffee-shop-dark.svg",
        "imageUrl": "https://navvo.io/uploads/place-images/e3/e3bacbd9-1e5d-474c-b84e-2fe7e1556541-dc3949fa.webp",
        "distanceKm": 0.55
      }
    ],
    "total": 1000,
    "page": 1,
    "limit": 10
  },
  "near": { "lat": 31.9539, "lng": 35.9106 },
  "index": { "provider": "navvo-search", "configured": true, "available": true, "mode": "keyword" }
}

فهم الاستعلام

يخبرك understanding كيف قرأت Navvo الاستعلام. النتائج تعكسه أصلًا، فلا يلزمك التصرّف بناءً عليه. استخدمه بدلًا من ذلك لتلميحات الواجهة، كإظهار شارة «مفتوح الآن» عندما يكتب المستخدم «مفتوح الآن». تُنتجه مجموعة قواعد دون أي نموذج، لذا تُقرأ الاستعلامات المتطابقة دائمًا بالطريقة نفسها، ويكون unavailable دائمًا false. وقد أُبقي الحقل للتوافق.

كل ما هو مفيد موجود تحت understanding.parsed:

الحقلالنوعالوصف
languagestringar أو en أو arabizi أو mixed أو unknown.
intentstringcategory: الاستعلام كله اسم تصنيف (pharmacy، صيدلية قريبة). وfood: طبق أو نوع طعام (shawarma، كنافة). وplace: أي شيء آخر، كاسم، أو خليط، أو كلمة تصنيف داخل استعلام أطول.
categorystringالاسم المعروض للتصنيف الرئيسي الذي يشير إليه الاستعلام. ويظهر أيضًا عندما ترد كلمة تصنيف داخل استعلام أطول.
categoriesstringحتى 6 معرّفات تصنيفات طابقها الاستعلام.
nearstring"me" عندما يطلب الاستعلام أماكن قريبة (near me، قريب مني، 2reeb).
openNowbooleantrue عندما يطلب الاستعلام أماكن مفتوحة (open now، مفتوح).
localitystringمنطقة وردت في الاستعلام، مثل Abdoun في cafe in Abdoun.
qualifierstringbest أو cheap أو open24 (مفتوح على مدار الساعة) أو onDuty (الصيدليات المناوبة، مناوبة) أو lateNight.

لا تظهر المفاتيح إلا عند انطباقها. بالنسبة إلى cafe in Abdoun:

"parsed": { "language": "en", "intent": "category", "category": "Coffee Shop", "categories": ["coffee-shop", "cafe", "coffee-stand", "cafeteria", "cat-cafe", "tea-house"], "locality": "Abdoun" }
العربيزي والنقحرة تُعالَج نيابةً عنك. يُجرَّب استعلام مثل saydaliyeh بالحروف العربية أيضًا، ويُجرَّب الاستعلام العربي بالحروف اللاتينية كذلك، لأن كثيرًا من الأماكن في الكتالوج تحمل أسماء إنجليزية منقحرة. لا حاجة أبدًا إلى النقحرة قبل الاستدعاء.

الأوجه

يضيف facets=category,amenities أعدادًا يمكنك تحويلها إلى شارات تصفية:

"facets": {
  "category": [
    { "slug": "coffee-shop", "name": { "en": "Coffee Shop", "ar": "مقهى" }, "count": 812 },
    { "slug": "cafe", "name": { "en": "Cafe", "ar": "مقهى" }, "count": 108 },
    { "slug": "coffee-roastery", "name": { "en": "Coffee Roastery", "ar": "محمصة قهوة" }, "count": 10 }
  ],
  "amenities": [
    { "slug": "wheelchair-accessible-entrance", "count": 301 },
    { "slug": "delivery", "count": 188 }
  ]
}
  • كل قائمة مرتَّبة حسب count، الأعلى أولًا. وقد يكون name.en أو name.ar لتصنيف ما null.
  • تشمل الأعداد الأماكن التي تطابق كلمات الاستعلام ومرشّحاتك. وقد تتضمّن items أيضًا نتائج قريبة أو نتائج بالمعنى، لذا تُرشد الأعداد واجهة التصفية ولا تمثّل تفصيلًا دقيقًا للقائمة.
  • مرّر أي slug مباشرةً كـ category= أو amenities= لتطبيق المرشّح.
  • يغيب facets إذا لم تطلبه، وقد يغيب عندما يجيب البديل (index.available: false).

الإبراز

مع highlight=true، يحمل العنصر الذي يطابق اسمُه الاستعلامَ highlight.nameEn و/أو highlight.nameAr. كلٌّ منهما هو الاسم مُهرَّبًا بصيغة HTML، مع إحاطة الكلمات المطابقة بـ <em>…</em>. ولا يظهر المفتاح إلا عندما يحتوي ذلك الاسم على تطابق:

"highlight": { "nameEn": "<em>Coffee</em> Factory &amp; Co. - Jabal Amman" }

إدراج السلسلة كـ HTML آمن. لكن النهج الأمتن هو عرضها كعُقد نصية: قسّمها عند الوسوم وفكّ ترميز الكيانات بنفسك، ولا تمرّرها أبدًا إلى innerHTML أو dangerouslySetInnerHTML:

// "<em>Coffee</em> Factory &amp; Co." -> [{ text: "Coffee", match: true }, { text: " Factory & Co.", match: false }]
function highlightSegments(html) {
  const decode = (s) => s
    .replace(/&lt;/g, "<").replace(/&gt;/g, ">")
    .replace(/&quot;/g, '"').replace(/&#39;/g, "'")
    .replace(/&amp;/g, "&");
  return html.split(/(<em>.*?<\/em>)/g).filter(Boolean).map((part) => {
    const m = part.match(/^<em>(.*)<\/em>$/);
    return { text: decode(m ? m[1] : part), match: Boolean(m) };
  });
}

didYouMean وجميع حقول GET /search/suggestions نص عادي لا يحمل أي وسوم.

تفاصيل النتيجة

يمكن أن يحمل العنصر ما تعرضه قائمة النتائج أو بطاقة الخريطة: reviewCount وcategoryName وpriceRange وpriceLevel وaddress وarea وhours وhighlights. يأتي كل منها من سجل المكان، ويُحذف إذا لم تتوفّر للمكان تلك البيانات، لذا تحقّق من وجود الحقل قبل استخدامه. وتظهر الحقول نفسها في suggestions عند عدم وجود نتائج وفي الأماكن المشابهة.

يصف hours اليوم الحالي بتوقيت الأردن، ويُحسب لحظة تنفيذ البحث، فلا تخزّن الاستجابة مؤقتًا أكثر من بضع دقائق.

الحقلالنوعالوصف
statestringopen أو closing (يغلق خلال 45 دقيقة) أو closed.
alwaysOpenbooleantrue عندما يكون المكان مفتوحًا على مدار الساعة: كل يوم، أو خلال الساعات الأربع والعشرين القادمة على الأقل (عدة أيام متتالية بدوام 24 ساعة). ولا يوجد عندها closesAt.
closesAtstringHH:MM: موعد إغلاق المكان المفتوح.
opensAtstringHH:MM: موعد فتح المكان المغلق التالي، خلال الأيام السبعة القادمة.
opensDaystringيوم ذلك الافتتاح، من sunday إلى saturday، إذا لم يكن اليوم.
hoursMayVarybooleantrue خلال عطلة رسمية في بلد المكان: قد تختلف ساعات اليوم.
"hours": { "state": "closed", "opensAt": "09:00", "opensDay": "sunday" }

يبقى المكان الذي يغلق الساعة 2 فجرًا open بعد منتصف الليل، مع "closesAt": "02:00".

الترتيب

يوضع كل مرشَّح أولًا في نطاق مطابقة. النطاقات لا تختلط، فالنطاق الأفضل يتقدّم دائمًا على الأسوأ:

  1. مطابقة تامة. الاستعلام هو اسم المكان أو أحد أسمائه البديلة، بما في ذلك بعد تحويل إملائي (استعلام بالعربيزي حُوِّل إلى العربية مثلًا).
  2. مطابقة قوية. يحتوي الاسم على كل كلمات الاستعلام مكتوبةً بشكل صحيح، أو يبدأ بما كتبه المستخدم مع mode=typeahead.
  3. مطابقة كاملة. كل الكلمات مطابقة مع السماح بأخطاء إملائية، أو تتوزّع الكلمات على الاسم والتصنيف والحيّ (cafe abdoun يجد مقهى في عبدون)، أو ينتمي المكان إلى التصنيف الذي يطلبه الاستعلام.
  4. مطابقة جزئية. بعض الكلمات فقط مطابقة.
  5. بالمعنى. عُثر على المكان عبر المطابقة بالمعنى وحدها.

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

  • بحث التصنيف يساوي بين الجميع. في pharmacy أو صيدلية قريبة لا يحظى مكان اسمه حرفيًا «صيدلية» بأي أفضلية. تتقدّم الأماكن القريبة والشائعة في ذلك التصنيف.
  • المناطق تنقل نقطة الأصل. في cafe in Abdoun تُرتَّب النتائج حول عبدون لا حول lat/lon. وبدون كلمة ربط (cafe abdoun) تبقى نقطة الأصل الخاصة بك وتحصل الأماكن في عبدون على تعزيز. وإذا كان الاستعلام كله اسم منطقة، تبحث Navvo عنها بالاسم.
  • المرافق المساندة تتراجع. مواقف الحافلات ومواقف السيارات ومواقف سيارات الأجرة والبوابات والمداخل وأجهزة الصراف الآلي تأتي بعد المكان الرئيسي ما لم يطلبها الاستعلام.
  • الأردن أولًا. بدون نقطة أصل، تتقدّم الأماكن في الأردن على مطابقات بالجودة نفسها في الخارج.
  • الفرع البعيد لا يتقدّم على الفروع القريبة. مع وجود نقطة أصل، تتنافس مطابقة الاسم التامة التي تبعد أكثر من 25 كم، من حيث المسافة، مع الأماكن الأقرب التي تتضمّن أسماؤها الاستعلام، فيعرض البحث عن carrefour من عمّان فروع عمّان أولًا. أما المكان الكبير فيحتفظ بتقدّمه مهما بعُد (Petra وAl-Aqsa Mosque).
  • «مفتوح الآن» في الاستعلام يؤخّر الأماكن المعروف أنها مغلقة (المفتوحة أولًا، ثم مجهولة الساعات، ثم المغلقة) حتى دون openNow=true. أما openNow=true فيزيل كل ما ليس مفتوحًا.
  • الأماكن المُموَّلة ذات الصلة بالاستعلام تحصل على تعزيز صغير داخل نطاقها، ولا تقفز أبدًا إلى نطاق أفضل. والنتائج التي تثبّتها قاعدة من Navvo تحمل promoted: true، وsponsored: true أيضًا عندما يكون الموضع مدفوعًا.

يحلّ sort=distance وsort=rating محلّ هذا الترتيب كليًّا.

المطابقة بالمعنى

تجد المطابقة بالكلمات الأماكن التي تحتوي أسماؤها وتصنيفاتها على كلمات الاستعلام. أمّا المطابقة بالمعنى فتجد أيضًا الأماكن التي تناسب وصفًا، مثل quiet place to study أو مكان للعشاء مع العائلة، حتى حين لا تتطابق أي كلمة، وذلك عبر العربية والإنجليزية أيضًا. وتعمل بالكامل على البنية التحتية الخاصة بـ Navvo، فلا يذهب نص الاستعلام إلى أي طرف ثالث.

  • هي بديل احتياطي فقط. لا تضيف نتائج إلا عندما تجد المطابقة بالكلمات مطابقات قوية قليلة. فالاستعلام الذي يملك مطابقات أسماء جيدة لا يتغيّر، ونتائج المعنى تأتي دائمًا بعد نتائج الكلمات (النطاق 5).
  • تحتاج إلى قرينة في الاستعلام: يجب أن تطابق كلمة واحدة على الأقل محتوى الدليل (مع التسامح مع الأخطاء الإملائية)، أو أن يسمّي الاستعلام فئة، أو أن يحمل مرشّحًا. ولا تحصل الحروف العشوائية والأسئلة غير المتعلقة بالأماكن على نتائج بالمعنى.
  • تتطلّب استعلامًا من كلمتين كاملتين على الأقل، وmode=submit، واستعلامًا ليس بحث تصنيف خالصًا. ولا تعمل أبدًا مع typeahead.
  • تنتظرها Navvo 350 مللي ثانية على الأكثر. إن كانت أبطأ أو غير متاحة، تحصل على نتائج الكلمات دونها ودون أي خطأ.
  • semantic=off يعطّلها. وsemantic=on يسمح بها في طلبات مفاتيح API، حيث تتصرّف auto مثل off.
  • يكون index.mode في الاستجابة hybrid عندما تُسهم المطابقة بالمعنى في تلك الاستجابة، وkeyword فيما عدا ذلك.

عند عدم وجود نتائج

عندما لا يطابق شيء، تكون places.items فارغة وplaces.total مساويًا 0، ولا تملأ Navvo القائمة أبدًا بأماكن غير ذات صلة. بدلًا من ذلك:

  • suggestions[] تسرد أماكن شائعة قرب نقطة الأصل، أو أماكن شائعة في الأردن عند غياب نقطة الأصل، بنفس بنية العناصر. اعرضها تحت عنوان مثل «لا نتائج — أماكن شائعة»، لا كنتائج.
  • didYouMean يظهر عندما يبدو الاستعلام خطأً إملائيًا لشيء موجود في المفردات المعتمدة لدى Navvo (أسماء التصنيفات وأسماء الأماكن المعروفة). اعرضه كرابط يعيد البحث.

ترقيم الصفحات

يتنقّل page وlimit في قائمة مرتَّبة واحدة. يرتّب كل استعلام أفضل 200 مرشَّح على الأكثر، لذا توقّف عندما تعود صفحة بعدد عناصر أقل من limit. ولا تحسب الصفحة الأخيرة من places.total، فهو تقدير.

لجلب التفاصيل الكاملة لمكان (ساعات العمل، الصور، المداخل)، استدعِ GET /places/{slug} باستخدام slug من إحدى النتائج.

الأخطاء

الحالةمتى
400q مفقود أو فارغ؛ أو معامل خارج قيمه المسموحة أو مداه (originType، mode، semantic، sort، minRating، radiusKm، أو locale أطول من 35 حرفًا، أو lat خارج −90…90، أو lon/lng خارج −180…180)؛ أو أُرسل lon وlng بقيمتين مختلفتين؛ أو أُرسل sort=distance أو radiusKm دون lat/lon.
401 / 403المفتاح مفقود أو غير صالح، أو يفتقر إلى النطاق search، أو تجاوز حصته (QUOTA_EXCEEDED).
429طلبات كثيرة جدًا من عنوان IP واحد (RATE_LIMITED).

إذا تعذّر الوصول إلى فهرس البحث، فلا يفشل /search. يجيب بديل أبسط من قاعدة البيانات بدلًا منه، ويكون index.available مساويًا false. وتتبع أجسام الأخطاء البنية القياسية الموضّحة في المواصفات.


القياس وحدود المعدّل

يُحتسب كل طلب بحث طلبًا واحدًا من حصة مفتاحك في الدقيقة واليوم، ويُحتسب طلبات موزونة لفوترة خطتك (راجع الخطط والقياس). أما المفتاح غير المحدود فلا حصة له، لكن طلباته تبقى موزونة:

نقطة النهايةالطلبات الموزونةالحدود
GET /search2حصة مفتاحك في الدقيقة واليوم (حدود المعدّل).
GET /search/suggestions1حصة مفتاحك.
GET /search/similar2حصة مفتاحك.
POST /search/events0 (غير مُقاسة)60 طلبًا في الدقيقة لكل عنوان IP للعميل (لا يسري على المفتاح غير المحدود)؛ وحتى 20 حدثًا و16 كيلوبايت لكل طلب.

لا تغيّر المطابقة بالمعنى وزن الطلب. والطلبات التي لا تحمل مفتاح API تحصل على المطابقة بالمعنى ضمن حصّة ساعية تقريبية لكل عنوان IP للعميل: نحو 120 بحثًا تعمل فيها المطابقة بالمعنى فعلًا، وبعد تجاوزها تكتفي بصمت بالمطابقة بالكلمات.

أثناء كتابة المستخدم، أبطئ معالجة الإدخال (debounce، نحو 250 مللي ثانية)، وأرسل mode=typeahead، وألغِ الطلب السابق عند وصول ضغطة مفتاح جديدة. وعند Enter أرسل طلبًا واحدًا بـ mode=submit. وعندما يختار المستخدم مكانًا من القائمة، افتحه مباشرةً بدل إطلاق بحث آخر.

حالة الفهرس والمراقبة

تحمل كل استجابة كائن index:

الحقلالنوعالوصف
providerstringدائمًا navvo-search.
configuredbooleanما إذا كان فهرس البحث مهيَّأً في هذا التثبيت.
availablebooleanما إذا كان الفهرس هو من أجاب عن هذا الطلب. false تعني أن بديلًا أبسط من قاعدة البيانات أجاب: تعود النتائج رغم ذلك، لكن التسامح مع الأخطاء الإملائية والأوجه والمطابقة بالمعنى غير متاحة.
modestringhybrid عندما تُسهم المطابقة بالمعنى في هذه الاستجابة، وkeyword فيما عدا ذلك.
تغيير كاسر لأنظمة المراقبة (2026-09-30). صار GET /api/v1/health يُبلغ عن search.engine بالقيمة navvo-search عندما يجيب الفهرس الكامل، أو fallback عندما يجيب البديل المتدهور من قاعدة البيانات. كانت الاستجابات السابقة تستخدم تسميات خاصة بالمحرّك. إذا كان نظام مراقبة أو تنبيه يقارن هذه السلسلة، فحدّثه إلى القيم الجديدة. أمّا search.configured فلم يتغيّر.
Copyright © 2026