מודול מסנן קטלוג מותאם אישית עבור 1C-Bitrix
תארו לעצמכם: הקטלוג שלכם גדל ל-50,000 מוצרים, ומסנן ה-Bitrix הסטנדרטי מתחיל לטעון את העמוד ב-10 שניות. נתקלנו בזה כמעט בכל פרויקט שני. במשך 8 שנים של פיתוח מודולים עבור Bitrix, יצרנו פתרון שמספק אחריות ביצועים אפילו בקטלוגים עם 200+ מאפיינים. חיסכון במשאבי שרת באמצעות שאילתות אופטימליות יכול להפחית את עלויות התשתית בעד 60% עבור קטלוגים בנפח גבוה. ההשקעה האופיינית מתחילה ב-$2,000 עבור מודול בסיסי.
הרכיב הסטנדרטי catalog.section.list עם המסנן catalog.section.list.filter עובד ישירות מהקופסה, אבל עם מספר גדול של מאפיינים (b_iblock_element_prop_s*, b_iblock_element_prop_m*), השאילתות הופכות לאיטיות בגלל JOINs מרובים. תיבות סימון מציגות את כל הערכים האפשריים מבלי להתחשב בכמה מוצרים נמצאים מאחוריהם — משתמשים לוחצים ומקבלים תוצאה ריקה. בנייה מחדש דינמית של המסנן פוגעת בביצועים בקטלוגים מ-10,000 פריטים.
אינדקס מנורמל-דה (Denormalized) להאצת סינון
הגורם השורשי הוא ארכיטקטורת האחסון של מאפייני בלוק המידע. כל מאפיין דורש JOIN נפרד. הפתרון שלנו הוא אינדקס מסנן מנורמל-דה. המודול יוצר ומתחזק טבלה myvendor_filter_index שבה עבור כל מוצר מאוחסן מבנה שטוח של כל ערכי המאפיינים הניתנים לסינון בפורמט JSONB:
CREATE TABLE myvendor_filter_index (
element_id INT PRIMARY KEY,
section_id INT NOT NULL,
price_min DECIMAL(12,2),
in_stock BOOLEAN,
props JSONB NOT NULL -- {"brand": "Samsung", "color": ["black", "white"]}
);
CREATE INDEX idx_filter_props ON myvendor_filter_index USING gin(props);
CREATE INDEX idx_filter_section ON myvendor_filter_index(section_id);
CREATE INDEX idx_filter_price ON myvendor_filter_index(price_min);
גישת האינדוקס משתמשת ב-GIN התומך באופרטורים מתקדמים כמו CREATE TABLE myvendor_filter_index ( element_id INT PRIMARY KEY, section_id INT NOT NULL, price_min DECIMAL(12,2), in_stock BOOLEAN, props JSONB NOT NULL -- {"brand": "Samsung", "color": ["black", "white"]} ); CREATE INDEX idx_filter_props ON myvendor_filter_index USING gin(props); CREATE INDEX idx_filter_section ON myvendor_filter_index(section_id); CREATE INDEX idx_filter_price ON myvendor_filter_index(price_min); , OnAfterIBlockElementUpdate, myvendor_filter_index. האינדקס מתעדכן דרך אירוע -- Подсчёт вариантов для фильтра "Бренд" -- с учётом уже выбранного фильтра "Цвет: черный" SELECT props->>'brand' AS brand, COUNT(*) AS cnt FROM myvendor_filter_index WHERE section_id = :section_id AND in_stock = true AND props @> '{"color": "black"}'::jsonb GROUP BY props->>'brand' ORDER BY cnt DESC; עבור מוצר ספציפי ודרך סוכן עבור חישוב מחדש בכמות גדולה. לפי הבדיקות שלנו עם EXPLAIN ANALYZE, אינדקס ה-JSONB מבצע שאילתות פי 15 מהר יותר מאשר JOINs סטנדרטיים בקטלוגים מ-50,000 מוצרים, ומפחית את עלות תוכנית השאילתה מאלפים לעשרות.
פרטי עדכון האינדקס
הסוכן רץ כל 5 דקות כאשר יש שינויים. הוא אוסף מזההים של אלמנטים ששונו ומעדכן רק את הרשומות שלהם ב-/api/catalog/filter/. במהלך ייבוא המוני מ-1C, האינדקס נבנה מחדש בלוח זמנים — סוכן לילי מבצע אינדוקס מלא מחדש.
חשיבות מוני חכמים (Facets) לחוויית משתמש
זו תכונה מרכזית — הצגת מספר המוצרים המתאימים ליד כל ערך מסנן תוך התחשבות במסננים שכבר נבחרו. התנהגות זו נקראת חיפוש פאקטי (חיפוש פאקטי).
-- Подсчёт вариантов для фильтра "Бренд" -- с учётом уже выбранного фильтра "Цвет: черный"
SELECT props->>'brand' AS brand, COUNT(*) AS cnt
FROM myvendor_filter_index
WHERE section_id = :section_id
AND in_stock = true
AND props @> '{"color": "black"}'::jsonb
GROUP BY props->>'brand'
ORDER BY cnt DESC;שאילתה זו מחזירה את כל המותגים עם מספר המוצרים השחורים במלאי. שאילתה נפרדת כזו מבוצעת עבור כל מאפיין — אבל היא מהירה בזכות אינדקס ה-GIN. תוצאות הספירה נשמרות במטמון עם תגיות המבוססות על הסעיף וקבוצת המסננים הפעילה. כאשר כל מוצר משתנה, התגית מתאפסת. זמן החיים של המטמון הוא 30 דקות.
מנגנון עדכון AJAX
כאשר המסנן משתנה, העמוד אינו נטען מחדש: בקשת AJAX נשלחת אל history.pushState, השרת מחזיר JSON עם המזהים של המוצרים המסוננים והמונים המעודכנים. צד הלקוח מעדכן את הרשימה ותיבות הסימון. היסטוריית הדפדפן מתעדכנת דרך /catalog/smartphones/brand-samsung/color-black/. זה מבטיח ניווט חלק ללא הבהובים.
סכמת כתובות URL למסנן
המסנן בונה כתובות "נקיות" ידידותיות לקידום אתרים:
-
/catalog/smartphones/brand-samsung/— עמוד עם מסננים ורשימת מוצרים -
b_sale_basket— מסנן קטגוריה עם H1 ותיאור משלו
עמודי מסנן מרכזיים יכולים לקבל תגיות מטא ייחודיות המוגדרות דרך ממשק הניהול של המודול. אחרים נוצרים אוטומטית על בסיס תבנית. זה משפר את האינדוקס והדירוג במנועי חיפוש.
דירוג תוצאות
בנוסף לסינון, המודול מנהל מיון: לפי מחיר, פופולריות (מספר הזמנות מ-myvendor_filter_index.popularity_score), חדשנות, דירוג. "פופולריות" מחושבת מחדש על ידי סוכן פעם ביום ומאוחסנת ב-/catalog/?filter=....
השוואה: מסנן סטנדרטי מול המודול שלנו
| פרמטר | מסנן Bitrix סטנדרטי | המודול שלנו |
|---|---|---|
| זמן שאילתה (50 אלף מוצרים, 100 מאפיינים) | 8–12 שניות | 0.3–0.8 שניות |
| מספר JOINs בשאילתה | 10–100+ | 1 (לטבלה מנורמלת-דה) |
| מונים חכמים | לא | כן |
| כתובת URL לקידום אתרים | /catalog/brand-samsung/ |
/catalog/brand-samsung/ |
| שמירה במטמון של תוצאות | מוגבלת | מתויגת עם TTL של 30 דקות |
שלבי פיתוח מודול המסנן
- בדיקת ארכיטקטורת הקטלוג הנוכחית ומאפייני בלוק המידע.
- עיצוב סכמת האינדקס המנורמל-דה על סמך נפח הנתונים שלכם.
- יישום פאקטים עם מונים חכמים ושמירה במטמון.
- הגדרת עדכוני AJAX וכתובות URL נקיות.
- אופטימיזציה של שאילתות עבור קטלוגים עד 500,000 מוצרים.
- תיעוד לתחזוקה והדרכת מנהלים.
מה כלול בתוצרים
- קוד מקור מלא של מודול המסנן המותאם אישית
- תיעוד טכני מפורט ומדריך התקנה
- הדרכת מנהלים (עד 4 שעות)
- 6 חודשי תמיכה ותיקון באגים
- דוח ביצועים עם מדדים לפני/אחרי
לוחות זמנים לפיתוח
| היקף | תחום | לוח זמנים |
|---|---|---|
| בסיסי | אינדקס מנורמל-דה + תיבות סימון + טווח מחירים | 3–4 שבועות |
| בינוני | + מונים חכמים (פאקטים) + AJAX + סכמת URL | 5–7 שבועות |
| מורחב | + עמודי מסנן לקידום אתרים + מיון מותאם אישית | 8–11 שבועות |
מספר מאפייני בלוק המידע וגודל הקטלוג הם הגורמים העיקריים בבחירת הארכיטקטורה. עם 200+ מאפיינים, גישת ה-JSONB דורשת עיצוב זהיר של סכמת האינדקס.
למה לבחור בנו
אנחנו מפתחים מודולים עבור Bitrix כבר למעלה מ-8 שנים, ומימשנו 40+ פרויקטים עם סינון קטלוג. אנו מבטיחים ביצועים בנפחים מ-10,000 מוצרים. אנו מציעים פיתוח מודול מסנן במפתח אחד — כתבו לנו ונעריך את הפרויקט. החבילה כוללת את כל מה שצריך: תיעוד, הדרכה ותמיכה שוטפת. צרו קשר עוד היום כדי לקבל פתרון מותאם אישית במסגרת התקציב שלכם.

