البحث
البحث
بحث نصّي حرّ في كتالوج الأماكن لدى 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 | الإبلاغ عن النتيجة التي فتحها المستخدم، بموافقته. |
- صار
localeيُحترَم ويُعاد صداه. كان يُسقَط سابقًا، فكانت كل استجابة تقولen. - صار
lat/lonيخضعان لفحص المدى، والإحداثي الواقع خارج الكرة الأرضية يعيد400. ويُقتطَعqعند 200 حرف. - يشمل
categoryالتصنيفات الفرعية: يعيدcategory=food-and-drinkالمقاهي والمطاعم والمخابز. - صار
understandingيأتي من المحلّل الحتمي ومتاحًا دائمًا. أمّا محتواه القديم الذي كان يولّده نموذج فقد زال.
GET /search
ابحث عن الأماكن باستعلام نصّي حر.
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"
معاملات الاستعلام
coffee in Abdoun، صيدلية مناوبة قريبة، saydaliyeh، Abdali Mall. يجب ألّا يكون فارغًا. ويُتجاهَل ما يتجاوز 200 حرف.en أو ar، أو وسم لغة كاملًا مثل ar-JO أو en-US (حتى 35 حرفًا). الوسوم التي تبدأ بـ ar تُحَلّ إلى ar وكل ما عداها إلى en، وتُعيد الاستجابة القيمة المُحلَّلة. لا يُصفّي locale النتائج أبدًا: تُطابَق الأسماء العربية والإنجليزية أيًّا كانت القيمة التي ترسلها.1. القيمة الافتراضية 1، والقيم الأصغر من 1 تُرفَع إلى 1.25، مُقيَّدة إلى 1–100. تُقيَّد القيم الخارجة عن المدى ولا تُرفَض.west,south,east,north. لا تُعاد إلا الأماكن الواقعة داخل الصندوق، وتُعيد الاستجابة bbox. تُتجاهَل القيمة المشوَّهة.−90 إلى 90. أرسله مع lon. تتقدّم الأماكن الأقرب ضمن نطاق المطابقة نفسه (انظر الترتيب)، لكن نقطة الأصل لا تُصفّي شيئًا إلا إذا أرسلت radiusKm أيضًا. تُعيد الاستجابة near: { lat, lng }. والقيمة غير الرقمية أو الخارجة عن المدى تعيد 400.−180 إلى 180. يُقبل lng كاسم بديل، وإرسال الاثنين بقيمتين مختلفتين يعيد 400.lon.device (الافتراضية) تعني موقع المستخدم نفسه. وmap تعني مركز الخريطة التي ينظر إليها: عندها يقلّ وزن المسافة ويتلاشى أثرها على نطاق أوسع، ولا تحمل العناصر distanceKm. أرسل map عندما توجّه بحثًا نصيًا عاديًا نحو ما يظهر على الشاشة لا نحو المستخدم.category=food-and-drink يشمل المقاهي والمطاعم والمخابز، وcategory=pharmacy يشمل الصيدليات فقط. أرسل عدة معرّفات مفصولة بفواصل لمطابقة أيٍّ منها: category=cafe,coffee-shop (حتى 10). المعرّفات من GET /places/categories، والقيمة التي ليست تصنيفًا لا تطابق شيئًا. تُعيد الاستجابة category.submit (الافتراضية) لبحث طلبه المستخدم، بالضغط على Enter مثلًا. وtypeahead للطلبات المُرسَلة أثناء الكتابة: تُعدّ مطابقات البادئة قوية، ويزداد وزن الأماكن الشائعة (فالمستخدم غالبًا يكتب اسمًا معروفًا)، ولا تعمل المطابقة بالمعنى أبدًا. كما يُعلِم تحليلات Navvo بأيّ الطلبات كانت ضغطات مفاتيح.auto (الافتراضية) أو on أو off. انظر المطابقة بالمعنى. مع مفتاح API تتصرّف auto مثل off، فأرسل on لتفعيلها.category أو amenities أو كلاهما. تُتجاهَل الأسماء غير المعروفة. انظر الأوجه.true، لا تُعاد إلا الأماكن المفتوحة الآن. يُقيَّم ذلك بتوقيت الأردن مع مراعاة العطل الرسمية. وتُستبعَد الأماكن التي لا تتوفّر لها بيانات ساعات العمل.0 إلى 5.1,2): 1 حتى 5 دنانير للشخص، و2 من 5 إلى 10 دنانير، و3 من 10 إلى 20 دينارًا، و4 أكثر من ذلك. يطابق المكان إذا وقع منتصف نطاق سعره المُدرَج، بعد تحويله إلى الدينار، ضمن أحد هذه المستويات. تُستبعد الأماكن التي لا يُدرَج لها سعر، ولا يُدرَج السعر إلا لبضعة آلاف من الأماكن (معظمها مقاهٍ ومطاعم)، لذا يعيد مرشّح السعر نتائج أقل بكثير.relevance (الافتراضية)، أو distance (الأقرب أولًا، ويتطلّب lat/lon)، أو rating (الأعلى تقييمًا أولًا). يحلّ distance وrating محلّ ترتيب الصلة كليًّا.lat/lon، من 0.1 إلى 500. يتطلّب نقطة أصل.wheelchair-accessible-entrance,delivery. هي معرّفات الخيارات نفسها في GET /places/facets ← options[].slug، أو يمكنك أخذها من facets=amenities.false فلا تحتفظ تحليلات البحث لدى Navvo بأي سجلّ لهذا البحث. هو مماثل لترويسة X-Navvo-Analytics: off، والإعداد المناسب للاختبارات وفحوص الجاهزية والمهام المجمَّعة.highlight، openNow، analytics) تقرأ true أو 1 على أنها صحيحة. وأي قيمة أخرى، بما فيها false و0 وyes، تُعدّ خاطئة. ولأن analytics مفعَّل افتراضيًا، فأي قيمة غير true/1 تُعطّله.ترويسات الطلب
هذه الترويسات كلها اختيارية. الأربع الأولى تتحكّم فيما تسجّله Navvo، وتشرح صفحة تحليلات البحث والخصوصية النموذج الذي تقوم عليه.
POST /search/events بهذا البحث، وتُحتسب سلسلة البحث أثناء الكتابة بحثًا واحدًا. الصيغة: من 16 إلى 64 حرفًا من A–Z a–z 0–9 _ -، دون ستة أرقام متتالية أو أكثر. وتُتجاهَل أي قيمة أخرى. لا تشتقّه أبدًا من معرّف مستخدم أو بريد إلكتروني أو رقم هاتف أو معرّف جهاز. لا تخزّن Navvo إلا تجزئة مُفتاحية له تُحسَب مع التاريخ، فلا يمكن ربط تجزئات الأيام المختلفة بعضها ببعض.off تُبقي هذا البحث خارج تحليلات البحث لدى Navvo، تمامًا مثل analytics=false.1 تعني أن متصفّح المستخدم يطلب عدم التتبّع (Global Privacy Control). عندها تتجاهل Navvo X-Navvo-Session وترفض الأحداث الخاصة بهذا البحث. ويبقى سجلّ البحث محفوظًا، لكن دون ربطه بجلسة.1 تمامًا مثل Sec-GPC: 1. إذا كنت تمرّر عمليات البحث عبر خادمك، فمرّر الترويستين كلتيهما من طلب المستخدم.sdk يميّز الطلبات الصادرة عن حزمة تطوير (SDK) مبنية على Navvo، والقيم الأخرى محجوزة لتطبيقات Navvo نفسها. تُصنَّف طلبات مفاتيح API التي لا تحمل sdk على أنها api. وتُرسل حزم Navvo نفسها القيمة sdk تلقائيًا: حزمتا الويب و Node ابتداءً من 0.2.1، وحزم Python و Go و Java ابتداءً من 0.2.0. وإذا كانت حزمة الويب تصل إلى الواجهة البرمجية عبر خادم وسيط خاص بك، فاسمح بترويسة الطلب هذه في سياسة CORS لديه.الاستجابة
| الحقل | النوع | الوصف |
|---|---|---|
query | string | استعلامك، يُعاد صداه. |
locale | string | اللغة المُحلَّلة: en أو ar. |
queryId | string | معرّف من 24 حرفًا لقائمة النتائج هذه. مرّره إلى POST /search/events عندما يفتح المستخدم نتيجة. وهو معرّف معتم: لا يحتوي على نص الاستعلام ولا على بيانات المستخدم، ويُصدَر معرّف جديد مع كل طلب. |
understanding | object | كيف قُرئ الاستعلام. انظر فهم الاستعلام. |
places.items[] | array | النتائج المرتَّبة (انظر أدناه). تكون فارغة عند عدم وجود تطابق: لا تحشو Navvo القائمة أبدًا بأماكن غير ذات صلة. |
places.total | number | عدد الأماكن المطابقة. على الفهرس هو تقدير سقفه 1,000، فتعامل معه على أنه «نحو N نتيجة». ولا يكون 0 إلا عند انعدام التطابق فعلًا. |
places.page / places.limit | number | صدى ترقيم الصفحات. |
facets | object | فقط عند طلب facets. انظر الأوجه. |
suggestions[] | array | فقط عندما تكون places.items فارغة: أماكن شائعة قرب نقطة الأصل تعرضها كبديل «لا نتائج — جرّب هذه». بنفس بنية places.items[]. انظر عند عدم وجود نتائج. |
didYouMean | string | فقط عند انعدام التطابق في استعلام يبدو خطأً إملائيًا: استعلام مُصحَّح مأخوذ من المفردات المعتمدة لدى Navvo. نص عادي. |
bbox / category / near | — | صدى bbox وcategory ونقطة الأصل التي أرسلتها. |
index | object | حالة فهرس البحث: { provider, configured, available, mode }. انظر حالة الفهرس والمراقبة. |
تحمل كل استجابة الترويسة Cache-Control: no-store. لكل استجابة queryId جديد، فالنسخة المخزَّنة مؤقتًا قد تربط نقرات المستخدم ببحث شخص آخر. لا تخزّن استجابات /search مؤقتًا في Service Worker ولا في شبكة توصيل محتوى.
كل عنصر من عناصر places.items[]:
| الحقل | النوع | الوصف |
|---|---|---|
id | string | معرّف المكان. |
slug | string | معرّف الرابط، يُستخدم مع GET /places/{slug}. |
nameEn / nameAr | string | null | الأسماء. |
nameEnTransliterated | boolean | يظهر بقيمة true فقط عندما يكون nameEn ناتجًا عن كتابة الاسم العربي بحروف لاتينية لعدم معرفة اسم إنجليزي (نحو 35,000 مكان). اعرض nameAr أولًا لهذه الأماكن، ولا تقدّم nameEn على أنه اسم رسمي. |
categories | string | معرّفات التصنيفات القياسية، والتصنيف الأساسي أولًا. |
canonicalCategorySlug | string | null | التصنيف الأساسي. |
rawCategories | string | التصنيفات الأصلية غير المُطبَّعة. |
rating | number | التقييم، أو 0 إن لم يوجد. |
sponsored | boolean | إدراج مُموَّل، أو موضع مدفوع وضعته قاعدة من Navvo. |
promoted | boolean | يظهر بقيمة true فقط عندما تضع قاعدة تحريرية أو ممولة من Navvo هذه النتيجة. ميّزها في واجهتك (مثلًا «مُروَّج»). |
center | string | الموقع بصيغة WKT على شكل POINT(<lng> <lat>)، خط الطول أولًا. |
lat / lng | number | null | الإحداثيات نفسها كأرقام، أو null عندما يكون center مفقودًا. |
iconLightUrl / iconDarkUrl | string | null | أيقونات دبوس التصنيف، كروابط مطلقة. انظر الأماكن ← أيقونات تصنيف الأماكن. |
imageUrl | string | null | صورة المكان كرابط مطلق، أو null عند عدم وجودها. انظر الأماكن ← صورة المكان. |
distanceKm | number | المسافة المستقيمة عن lat/lon بالكيلومترات. تظهر فقط مع نقطة أصل من نوع الجهاز (originType=device، الافتراضية). |
highlight | object | مع highlight=true: { nameEn?, nameAr? }. انظر الإبراز. |
reviewCount | number | عدد المراجعات التي يستند إليها rating. يظهر عند توفّره. |
categoryName | string | اسم الفئة الرئيسية للعرض بلغة locale في الاستجابة، مثل Coffee Shop أو مقهى. |
priceRange | string | الإنفاق المعتاد للشخص كما هو مُدرَج، مثل JOD 5–10. يظهر عند توفّره. |
priceLevel | number | من 1 إلى 4: المستوى الذي يرشّح عليه price، ويُحسب من priceRange (مثل $ إلى $$$$). يظهر عندما يمكن قراءة priceRange. |
address | string | عنوان شارع قصير يُعرض في سطر واحد، بخط لغة locale في الاستجابة إن وُجد للمكان، مثل Al-Mutanabbi St. 22. |
area | string | الحي أو المنطقة، مثل Zahran. |
hours | object | حالة الدوام اليوم بتوقيت الأردن. انظر تفاصيل النتيجة. يغيب إذا لم تكن للمكان ساعات عمل. |
highlights | string | حتى ثلاثة أشياء يُعرف بها المكان، مثل 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:
| الحقل | النوع | الوصف |
|---|---|---|
language | string | ar أو en أو arabizi أو mixed أو unknown. |
intent | string | category: الاستعلام كله اسم تصنيف (pharmacy، صيدلية قريبة). وfood: طبق أو نوع طعام (shawarma، كنافة). وplace: أي شيء آخر، كاسم، أو خليط، أو كلمة تصنيف داخل استعلام أطول. |
category | string | الاسم المعروض للتصنيف الرئيسي الذي يشير إليه الاستعلام. ويظهر أيضًا عندما ترد كلمة تصنيف داخل استعلام أطول. |
categories | string | حتى 6 معرّفات تصنيفات طابقها الاستعلام. |
near | string | "me" عندما يطلب الاستعلام أماكن قريبة (near me، قريب مني، 2reeb). |
openNow | boolean | true عندما يطلب الاستعلام أماكن مفتوحة (open now، مفتوح). |
locality | string | منطقة وردت في الاستعلام، مثل Abdoun في cafe in Abdoun. |
qualifier | string | best أو 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 & Co. - Jabal Amman" }
إدراج السلسلة كـ HTML آمن. لكن النهج الأمتن هو عرضها كعُقد نصية: قسّمها عند الوسوم وفكّ ترميز الكيانات بنفسك، ولا تمرّرها أبدًا إلى innerHTML أو dangerouslySetInnerHTML:
// "<em>Coffee</em> Factory & Co." -> [{ text: "Coffee", match: true }, { text: " Factory & Co.", match: false }]
function highlightSegments(html) {
const decode = (s) => s
.replace(/</g, "<").replace(/>/g, ">")
.replace(/"/g, '"').replace(/'/g, "'")
.replace(/&/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 اليوم الحالي بتوقيت الأردن، ويُحسب لحظة تنفيذ البحث، فلا تخزّن الاستجابة مؤقتًا أكثر من بضع دقائق.
| الحقل | النوع | الوصف |
|---|---|---|
state | string | open أو closing (يغلق خلال 45 دقيقة) أو closed. |
alwaysOpen | boolean | true عندما يكون المكان مفتوحًا على مدار الساعة: كل يوم، أو خلال الساعات الأربع والعشرين القادمة على الأقل (عدة أيام متتالية بدوام 24 ساعة). ولا يوجد عندها closesAt. |
closesAt | string | HH:MM: موعد إغلاق المكان المفتوح. |
opensAt | string | HH:MM: موعد فتح المكان المغلق التالي، خلال الأيام السبعة القادمة. |
opensDay | string | يوم ذلك الافتتاح، من sunday إلى saturday، إذا لم يكن اليوم. |
hoursMayVary | boolean | true خلال عطلة رسمية في بلد المكان: قد تختلف ساعات اليوم. |
"hours": { "state": "closed", "opensAt": "09:00", "opensDay": "sunday" }
يبقى المكان الذي يغلق الساعة 2 فجرًا open بعد منتصف الليل، مع "closesAt": "02:00".
الترتيب
يوضع كل مرشَّح أولًا في نطاق مطابقة. النطاقات لا تختلط، فالنطاق الأفضل يتقدّم دائمًا على الأسوأ:
- مطابقة تامة. الاستعلام هو اسم المكان أو أحد أسمائه البديلة، بما في ذلك بعد تحويل إملائي (استعلام بالعربيزي حُوِّل إلى العربية مثلًا).
- مطابقة قوية. يحتوي الاسم على كل كلمات الاستعلام مكتوبةً بشكل صحيح، أو يبدأ بما كتبه المستخدم مع
mode=typeahead. - مطابقة كاملة. كل الكلمات مطابقة مع السماح بأخطاء إملائية، أو تتوزّع الكلمات على الاسم والتصنيف والحيّ (
cafe abdounيجد مقهى في عبدون)، أو ينتمي المكان إلى التصنيف الذي يطلبه الاستعلام. - مطابقة جزئية. بعض الكلمات فقط مطابقة.
- بالمعنى. عُثر على المكان عبر المطابقة بالمعنى وحدها.
داخل النطاق الواحد، تجمع 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 من إحدى النتائج.
الأخطاء
| الحالة | متى |
|---|---|
400 | q مفقود أو فارغ؛ أو معامل خارج قيمه المسموحة أو مداه (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 /search | 2 | حصة مفتاحك في الدقيقة واليوم (حدود المعدّل). |
GET /search/suggestions | 1 | حصة مفتاحك. |
GET /search/similar | 2 | حصة مفتاحك. |
POST /search/events | 0 (غير مُقاسة) | 60 طلبًا في الدقيقة لكل عنوان IP للعميل (لا يسري على المفتاح غير المحدود)؛ وحتى 20 حدثًا و16 كيلوبايت لكل طلب. |
لا تغيّر المطابقة بالمعنى وزن الطلب. والطلبات التي لا تحمل مفتاح API تحصل على المطابقة بالمعنى ضمن حصّة ساعية تقريبية لكل عنوان IP للعميل: نحو 120 بحثًا تعمل فيها المطابقة بالمعنى فعلًا، وبعد تجاوزها تكتفي بصمت بالمطابقة بالكلمات.
mode=typeahead، وألغِ الطلب السابق عند وصول ضغطة مفتاح جديدة. وعند Enter أرسل طلبًا واحدًا بـ mode=submit. وعندما يختار المستخدم مكانًا من القائمة، افتحه مباشرةً بدل إطلاق بحث آخر.حالة الفهرس والمراقبة
تحمل كل استجابة كائن index:
| الحقل | النوع | الوصف |
|---|---|---|
provider | string | دائمًا navvo-search. |
configured | boolean | ما إذا كان فهرس البحث مهيَّأً في هذا التثبيت. |
available | boolean | ما إذا كان الفهرس هو من أجاب عن هذا الطلب. false تعني أن بديلًا أبسط من قاعدة البيانات أجاب: تعود النتائج رغم ذلك، لكن التسامح مع الأخطاء الإملائية والأوجه والمطابقة بالمعنى غير متاحة. |
mode | string | hybrid عندما تُسهم المطابقة بالمعنى في هذه الاستجابة، وkeyword فيما عدا ذلك. |
GET /api/v1/health يُبلغ عن search.engine بالقيمة navvo-search عندما يجيب الفهرس الكامل، أو fallback عندما يجيب البديل المتدهور من قاعدة البيانات. كانت الاستجابات السابقة تستخدم تسميات خاصة بالمحرّك. إذا كان نظام مراقبة أو تنبيه يقارن هذه السلسلة، فحدّثه إلى القيم الجديدة. أمّا search.configured فلم يتغيّر.