יישום תיוג פשוט עם חיפוש אלסטיקה

עליון התמדה

רק הכרזתי על החדש למד אביב קורס, המתמקד ביסודות האביב 5 ומגף האביב 2:

>> בדוק את הקורס מאמר זה הוא חלק מסדרה: • יישום תיוג פשוט עם חיפוש אלסטיקה (מאמר נוכחי) • יישום תיוג פשוט עם JPA

• יישום תיוגים מתקדם עם JPA

• יישום תיוג פשוט עם MongoDB

1. סקירה כללית

תיוג הוא דפוס עיצוב נפוץ המאפשר לנו לסווג ולסנן פריטים במודל הנתונים שלנו.

במאמר זה נבצע תיוג באמצעות Spring and Elasticsearch. נשתמש בנתוני אביב ובממשק ה- Elasticsearch.

קודם כל, אנחנו לא הולכים לכסות את היסודות של קבלת נתונים על אלסטיקה ונתוני אביב - תוכלו לחקור אותם כאן.

2. הוספת תגים

היישום הפשוט ביותר של תיוג הוא מערך מחרוזות. אנו יכולים ליישם זאת על ידי הוספת שדה חדש למודל הנתונים שלנו כך:

@Document (indexName = "blog", type = "article") כיתה ציבורית מאמר {// ... @Field (type = Keyword) תגי מחרוזת פרטיים []; // ...}

שימו לב לשימוש ב- מילת מפתח סוג שדה. אנו רוצים רק התאמות מדויקות של התגים שלנו כדי לסנן תוצאה. זה מאפשר לנו להשתמש בתגים דומים אך נפרדים כמו elasticsearchIsAwesome ו אלסטיות חיפוש זה נורא.

שדות מנותחים יחזירו התאמות חלקיות וזו התנהגות שגויה במקרה זה.

3. שאילתות בנייה

תגים מאפשרים לנו לתפעל את השאילתות שלנו בדרכים מעניינות. אנחנו יכולים לחפש אותם כמו בכל תחום אחר, או להשתמש בהם כדי לסנן את התוצאות שלנו match_all שאילתות. אנו יכולים להשתמש בהם גם בשאילתות אחרות כדי להדק את התוצאות שלנו.

3.1. חיפוש תגים

החדש תָג שדה שיצרנו במודל שלנו הוא בדיוק כמו כל תחום אחר באינדקס שלנו. אנו יכולים לחפש כל ישות שיש לה תג ספציפי כזה:

@Query ("{\" bool \ ": {\" must \ ": [{\" match \ ": {\" tags \ ": \"? 0 \ "}}}}") דף findByTagUsingDeclaredQuery (מחרוזת תג, Pageable pageable);

דוגמה זו משתמשת במאגר נתונים של Spring לצורך בניית השאילתה שלנו, אך אנו יכולים באותה מהירות להשתמש בתבנית Rest כדי לשאול ידנית את אשכול Elasticsearch.

באופן דומה, אנו יכולים להשתמש ב- API של Elasticsearch:

boolQuery (). must (termQuery ("tags", "elasticsearch"));

נניח שאנו משתמשים במסמכים הבאים באינדקס שלנו:

[{"id": 1, "title": "Spring Data Elasticsearch", "מחברים": [{"name": "John Doe"}, {"name": "John Smith"}], "tags": ["elasticsearch", "data spring"]}, {"id": 2, "title": "מנועי חיפוש", "מחברים": [{"name": "John Doe"}], "tags": [ "מנועי חיפוש", "הדרכה"]}, {"id": 3, "title": "מאמר שני על חיפוש אלסטיקה", "מחברים": [{"name": "John Smith"}], "tags": ["elasticsearch", "data spring"]}, {"id": 4, "title": "הדרכה בחיפושי אלסטיקה", "מחברים": [{"name": "John Doe"}], "tags": [ "elasticsearch"]},]

כעת נוכל להשתמש בשאילתה זו:

עמוד ArticleByTags = articleService.findByTagUsingDeclaredQuery ("חיפוש אלסטיות", PageRequest.of (0, 10)); // articleByTags יכיל 3 מאמרים [1, 3, 4] assertThat (articleByTags, containInAnyOrder (hasProperty ("id", is (1)), hasProperty ("id", is (3)), hasProperty ("id", הוא (4))));

3.2. סינון כל המסמכים

דפוס עיצובי נפוץ הוא יצירת a תצוגת רשימה מסוננת בממשק המשתמש שמציג את כל הישויות, אך גם מאפשר למשתמש לסנן על סמך קריטריונים שונים.

נניח שאנחנו רוצים להחזיר את כל המאמרים המסוננים לפי התג שהמשתמש יבחר:

@Query ("{\" bool \ ": {\" must \ ":" + "{\" match_all \ ": {}}, \" filter \ ": {\" term \ ": {\" tags \ ": \"? 0 \ "}}}}") עמוד findByFilteredTagQuery (תג מחרוזת, עמוד pageable);

שוב אנו משתמשים בנתוני אביב כדי לבנות את השאילתה המוצהרת שלנו.

כתוצאה מכך, השאילתה בה אנו משתמשים מחולקת לשני חלקים. שאילתת הניקוד היא המונח הראשון, במקרה זה, match_all. שאילתת המסנן היא הבאה ומספרת ל- Elasticsearch אילו תוצאות יש להשליך.

כך אנו משתמשים בשאילתה זו:

עמוד ArticleByTags = articleService.findByFilteredTagQuery ("חיפוש אלסטיות", PageRequest.of (0, 10)); // articleByTags יכיל 3 מאמרים [1, 3, 4] assertThat (articleByTags, containInAnyOrder (hasProperty ("id", is (1)), hasProperty ("id", is (3)), hasProperty ("id", הוא (4))));

חשוב להבין שלמרות שזה מחזיר את אותן תוצאות כמו הדוגמה שלנו לעיל, שאילתה זו תניב ביצועים טובים יותר.

3.3. שאילתות סינון

לפעמים חיפוש מחזיר יותר מדי תוצאות כדי להיות שמיש. במקרה כזה, נחמד לחשוף מנגנון סינון שיכול להפעיל מחדש את אותו החיפוש, רק עם התוצאות מצטמצמות.

הנה דוגמה שבה אנו מצמצמים את המאמרים שכתב מחבר, רק למאמרים עם תג ספציפי:

@Query ("{\" bool \ ": {\" חייב \ ":" + "{\" להתאים \ ": {\" מחברים.שם \ ": \"? 0 \ "}}," + "\ "filter \": {\ "מונח \": {\ "תגים \": \ "? 1 \"}}}} ") דף findByAuthorsNameAndFilteredTagQuery (שם מחרוזת, תג מחרוזת, תומכי דף)

שוב, Spring Data עושה את כל העבודה בשבילנו.

בואו נסתכל גם כיצד לבנות שאילתה זו בעצמנו:

בונה QueryBuilder = boolQuery (). Must (nestedQuery ("מחברים", boolQuery (). Must (termQuery ("מחברים.שם", "איילה")), ScoreMode.None)). פילטר (termQuery ("תגיות", ") חיפוש אלסטי "));

אנו יכולים, כמובן, להשתמש באותה טכניקה לסינון בכל תחום אחר במסמך. אבל תגים מעניקים את עצמם טוב במיוחד למקרה השימוש הזה.

כך תשתמש בשאילתה שלעיל:

SearchQuery searchQuery = חדש NativeSearchQueryBuilder (). WithQuery (builder) .build (); מאמרי רשימה = elasticsearchTemplate.queryForList (searchQuery, Article.class); // מאמרים מכילים [1, 4] assertThat (articleByTags, containInAnyOrder (hasProperty ("id", is (1)), hasProperty ("id", is (4))));

4. סינון הקשר

כשאנחנו בונים שאילתה, עלינו להבדיל בין הקשר שאילתה לבין הקשר המסנן. לכל שאילתה ב- Elasticsearch יש הקשר שאילתה, כך שאנחנו צריכים להיות רגילים לראות אותם.

לא כל סוג שאילתות תומך בהקשר המסנן. לכן אם אנו רוצים לסנן על תגים, עלינו לדעת באילו סוגי שאילתות אנו יכולים להשתמש.

ה בול לשאילתה יש שתי דרכים לגשת להקשר המסנן. הפרמטר הראשון, לְסַנֵן, היא זו בה אנו משתמשים לעיל. אנו יכולים גם להשתמש ב- אסור פרמטר להפעלת ההקשר.

סוג השאילתה הבא שנוכל לסנן הוא קבוע_ציון. זה שימושי כאשר uu רוצה להחליף את הקשר השאילתה בתוצאות המסנן ולהקצות לכל תוצאה את אותה הציון.

סוג השאילתה הסופי שנוכל לסנן על בסיס תגים הוא צבירת מסננים. זה מאפשר לנו ליצור קבוצות צבירה על בסיס תוצאות המסנן שלנו. במילים אחרות, אנו יכולים לקבץ את כל המאמרים לפי תג בתוצאת הצבירה שלנו.

5. תיוג מתקדם

עד כה דיברנו רק על תיוג באמצעות היישום הבסיסי ביותר. השלב ההגיוני הבא הוא ליצור תגים שהם עצמם צמדי ערך מפתח. זה יאפשר לנו להיות אפילו יותר חובבים עם השאילתות והמסננים שלנו.

לדוגמה, נוכל לשנות את שדה התגים שלנו כך:

תגי רשימה פרטיים @Field (type = Nested);

ואז פשוט נשנה את המסננים שלנו לשימוש nestedQuery סוגים.

ברגע שאנחנו מבינים איך להשתמש צמדי ערך מפתח זהו צעד קטן לשימוש בחפצים מורכבים כתגית שלנו. לא הרבה יישומים יזדקקו לאובייקט מלא כתג, אך טוב לדעת שיש לנו אפשרות זו אם נצטרך זאת.

6. מסקנה

במאמר זה סקרנו את יסודות הטמעת התיוג באמצעות Elasticsearch.

כמו תמיד, ניתן למצוא דוגמאות ב- GitHub.

הַבָּא » יישום תיוג פשוט בתחתית JPA Persistence

רק הכרזתי על החדש למד אביב קורס, המתמקד ביסודות האביב 5 ומגף האביב 2:

>> בדוק את הקורס