כאשר אתר עולה על 100,000 עמודים, שאילתות SQL LIKE סטנדרטיות מתחילות להיכשל. נתקלנו שוב ושוב בפרויקטים שבהם זמני החיפוש הגיעו ל-5–10 שניות, מה שהרחיק משתמשים ופגע בהמרות. לדוגמה, בפרויקט אחד עם קטלוג של 3 מיליון מוצרים, לאחר הטמעת Manticore, זמן החיפוש הממוצע ירד מ-7 שניות ל-35 אלפיות השנייה, ועומס שרת מסד הנתונים ירד פי 10. מנוע חיפוש בטקסט מלא כמו Manticore Search פותר את הבעיה — זמני התגובה יורדים ל-20–50 אלפיות השנייה. אנו משתמשים ב-Manticore Search 6.x ב-Docker עם PHP 8.x ו-PDO. עם ניסיון של למעלה מ-5 שנים ויותר מ-30 אינטגרציות מוצלחות, אנו מחברים ומגדירים את Manticore עבור הפרויקט שלך.
אילו בעיות אנו פותרים?
- חיפוש איטי עם נפחי נתונים גדולים. Manticore מעבד שאילתות על אינדקסים של מאות ג'יגה-בייט באלפיות השנייה. שאילתות SQL LIKE טיפוסיות גורמות לסריקות טבלה מלאות ולבעיית N+1 — Manticore נמנע מכך הודות לאינדקסים הפוכים.
-
מורפולוגיה רוסית מורכבת. ה-stemmer המובנה
stem_ruוה-lemmatizerlemmatize_ru_allמטפלים נכון במקרים ובצורות מילים. הגדרה זו היא חובה עבור תוכן בשפה הרוסית. - צורך בדירוג תוצאות. אנו מגדירים משקלי שדות, BM25, שקלול לפי דירוג ותאריך — החיפוש מחזיר את התוצאות הרלוונטיות ביותר ראשונות. לדוגמה, משקל כותרת מאמר 10, משקל גוף 1, משקל מחבר 2.
- סנכרון עם מסד הנתונים הראשי. אנו מיישמים עדכוני אינדקס מונעי אירועים באמצעות Observer או אינדוקס אצווה. ללא סנכרון, החיפוש מחזיר נתונים מיושנים.
למה Manticore על פני Sphinx לפרויקטים חדשים?
Manticore מפותח באופן פעיל: הוא תומך במסמכי JSON, HTTP API, ואחסון עמודי. מהירות החיפוש גבוהה ב-20–30% הודות לאופטימיזציות בגרסה 6.x. Elasticsearch איטי פי 2–3 בשאילתות טקסט מלא פשוטות, ועלויות הרישוי נמוכות יותר. לפי התיעוד הרשמי של Manticore, מהירות החיפוש על אינדקסי RT מגיעה ל-10,000 שאילתות בשנייה. אם יש לך Sphinx legacy — אנו מסייעים בהעברה ל-Manticore ללא השבתת שירות.
מה מציעה המורפולוגיה לרוסית?
שים לב: כפי שנאמר ב-תיעוד המורפולוגיה של Manticore, ה-stemmer stem_ru וה-lemmatizer lemmatize_ru_all מבטיחים זיהוי נכון של מקרים וצורות מילים. ללא הגדרה זו, חיפוש של "автомобиль" לא ימצא את "автомобиля" או "автомобилей". זה קריטי עבור תוכן בשפה הרוסית.
כיצד אנו מגדירים חיפוש: מחסנית ודוגמה
אנו משתמשים ב-Manticore Search 6.x, Docker, PHP 8.x עם PDO. בפרויקט טיפוסי, אנו פורסים קונטיינר, מגדירים אינדקס RT עם מורפולוגיה רוסית, ומתחברים דרך פרוטוקול MySQL. להלן דוגמת התצורה והקוד.
התקנת Manticore Search
---
# docker-compose.yml services:
manticore:
image: manticoresearch/manticore:6.2.12
environment:
- EXTRA=1
ports:
- "9306:9306" # MySQL-совместимый порт
- "9308:9308" # HTTP API
volumes:
- manticore_data:/var/lib/manticore
- ./manticore.conf:/etc/manticoresearch/manticore.conf
--- תצורת אינדקס
# manticore.conf
index articles
{
type = rt
path = /var/lib/manticore/articles
rt_field = title
rt_field = body
rt_field = author
rt_attr_uint = category_id
rt_attr_bigint = created_at
rt_attr_float = rating
rt_attr_string = slug
morphology = stem_ru, stem_en
min_word_len = 2
expand_keywords = 1
min_infix_len = 3
stopwords = /etc/manticoresearch/stopwords_ru.txt
}
searchd
{
listen = 0.0.0.0:9306:mysql41
listen = 0.0.0.0:9308:http
log = /var/log/manticore/searchd.log
query_log = /var/log/manticore/query.log
max_matches = 10000
} חיבור דרך פרוטוקול MySQL (PHP)
$pdo = new PDO('mysql:host=localhost;port=9306;charset=utf8', '', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Вставка документа
$stmt = $pdo->prepare("
INSERT INTO articles (id, title, body, author, category_id, created_at, rating)
VALUES (:id, :title, :body, :author, :category_id, :created_at, :rating)
");
$stmt->execute([
'id' => $article->id,
'title' => $article->title,
'body' => strip_tags($article->content),
'author' => $article->user->name,
'category_id' => $article->category_id,
'created_at' => $article->created_at->timestamp,
'rating' => $article->rating,
]);
// Полнотекстовый поиск с весами полей
$stmt = $pdo->prepare("
SELECT id, title, author, rating, WEIGHT() AS relevance
FROM articles
WHERE MATCH(:query)
ORDER BY relevance DESC, rating DESC
LIMIT :offset, :limit
OPTION ranker=bm25, field_weights=(title=10, body=1, author=2)
");
סנכרון עם מסד הנתונים
class ArticleObserver {
public function saved(Article $article): void
{
ManticoreIndexJob::dispatch($article->id);
}
public function deleted(Article $article): void
{
ManticoreDeleteJob::dispatch($article->id);
}
} הדגשת תוצאות (snippet)
SELECT id, title, SNIPPET(body, :query, 'limit=200, around=5, html_strip_mode=strip') AS excerpt
FROM articles
WHERE MATCH(:query)
LIMIT 20 תהליך העבודה
- ניתוח דרישות החיפוש: נפח נתונים, סוגי תוכן, צורך במורפולוגיה.
- עיצוב סכמת אינדקס: שדות, מאפיינים, משקלים.
- פריסת Manticore ב-Docker והגדרת הגדרות.
- כתיבת קוד אינדוקס: טעינה ראשונית, עדכונים מצטברים.
- הטמעת API חיפוש באפליקציה עם דירוג ו-snippets.
- UI: תיבת חיפוש, תוצאות, דפדוף, הדגשה.
- בדיקות: בדיקות עומס, בדיקות רלוונטיות.
- פריסה וניטור.
מה כלול בעבודה
- התקנה והגדרה של Manticore Search ב-Docker.
- יצירת אינדקס RT עם מורפולוגיה, מילות עצירה, infixes.
- פיתוח מודול סנכרון נתונים (Observer או אצווה).
- REST API לחיפוש (SQL או JSON).
- התאמת Frontend: סרגל חיפוש, snippets, דפדוף.
- בדיקות עומס ואופטימיזציה.
- תיעוד תפעול ופרטי גישה.
לוחות זמנים
| שלב | זמן |
|---|---|
| התקנה והגדרה | יום אחד |
| אינדוקס ראשוני + מסנכרן | יומיים |
| API חיפוש + בדיקות | יומיים |
| אינטגרציית UI | 1–2 ימים |
| סה"כ | 6–7 ימי עבודה |
שגיאות טיפוסיות והפתרונות שלהן
| שגיאה | פתרון |
|---|---|
| הגדרת מורפולוגיה שגויה (החיפוש לא מוצא צורות מילים) | ציין # docker-compose.yml services: manticore: image: manticoresearch/manticore:6.2.12 environment: - EXTRA=1 ports: - "9306:9306" # MySQL-совместимый порт - "9308:9308" # HTTP API volumes: - manticore_data:/var/lib/manticore - ./manticore.conf:/etc/manticoresearch/manticore.conf |
| מילות עצירה חסרות (האינדקס עמוס במילות יחס) | הוסף קובץ stopwords עם רשימת מילות עצירה |
| סנכרון לא מוגדר (החיפוש מחזיר נתונים מיושנים) | הטמע Observer עבור אירועי שמירה/מחיקה |
מגבלת # manticore.conf index articles { type = rt path = /var/lib/manticore/articles rt_field = title rt_field = body rt_field = author rt_attr_uint = category_id rt_attr_bigint = created_at rt_attr_float = rating rt_attr_string = slug morphology = stem_ru, stem_en min_word_len = 2 expand_keywords = 1 min_infix_len = 3 stopwords = /etc/manticoresearch/stopwords_ru.txt } searchd { listen = 0.0.0.0:9306:mysql41 listen = 0.0.0.0:9308:http log = /var/log/manticore/searchd.log query_log = /var/log/manticore/query.log max_matches = 10000 } קטנה מדי (תוצאות נחתכות) | הגדל ל-10,000 או לערך הנדרש |
| חסרים snippets (המשתמש לא רואה הקשר) | השתמש בפונקציית $pdo = new PDO('mysql:host=localhost;port=9306;charset=utf8', '', ''); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Вставка документа $stmt = $pdo->prepare(" INSERT INTO articles (id, title, body, author, category_id, created_at, rating) VALUES (:id, :title, :body, :author, :category_id, :created_at, :rating) "); $stmt->execute([ 'id' => $article->id, 'title' => $article->title, 'body' => strip_tags($article->content), 'author' => $article->user->name, 'category_id' => $article->category_id, 'created_at' => $article->created_at->timestamp, 'rating' => $article->rating, ]); // Полнотекстовый поиск с весами полей $stmt = $pdo->prepare(" SELECT id, title, author, rating, WEIGHT() AS relevance FROM articles WHERE MATCH(:query) ORDER BY relevance DESC, rating DESC LIMIT :offset, :limit OPTION ranker=bm25, field_weights=(title=10, body=1, author=2) "); בשאילתה |
סנכרון אינדקס בזמן אמת
אנו משתמשים בתבנית Observer: כאשר רשומה נשמרת או נמחקת ב-Eloquent (Laravel), אנו שולחים Job לעדכון האינדקס. לטעינת אצווה של נפחי נתונים גדולים, אנו משתמשים בתהליך רקע שמבצע אינדוקס של אצוות של 1000 רשומות. זה שומר על האינדקס מעודכן ללא עיכובים.
הזמנת אינטגרציית חיפוש
צור קשר לייעוץ והערכת פרויקט. אנו ננתח את מבנה הנתונים, העומס ודרישות החיפוש שלך, ונציע פתרון אופטימלי. אנו מספקים פרויקט מפתח ב-6–7 ימים. יציבות מובטחת ותוצאות רלוונטיות. קבל ייעוץ על אינטגרציית Manticore בפרויקט שלך עוד היום.







