תמיכה גיאו-מרחבית ב- ElasticSearch

1.מבוא

Elasticsearch ידוע בעיקר בזכות יכולות החיפוש בטקסט מלא, אך הוא כולל גם תמיכה גיאו-מרחבית מלאה.

אנו יכולים למצוא מידע נוסף על הגדרת Elasticsearch ועל תחילת העבודה במאמר הקודם.

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

2. סוג נתונים גיאוגרפיים

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

מיפוי דינמי לא יעבוד בזמן הגדרת מיפוי לסוגי גיאוגרפיה.

Elasticsearch מציע שתי דרכים לייצג גיאוגרפיה:

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

בואו נסתכל לעומק על כל אחת מהקטגוריות שלעיל:

2.1. סוג נתונים של Geo Point

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

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

להלן מיפוי לדוגמה לשדה לשמירת נתוני נקודות גיאוגרפיות:

PUT / index_name {"mappings": {"TYPE_NAME": {"נכסים": {"location": {"type": "geo_point"}}}}

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

2.2. סוג נתונים של צורה גיאוגרפית

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

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

PUT / index_name {"mappings": {"TYPE_NAME": {"נכסים": {"location": {"type": "geo_shape"}}}}

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

3. דרכים שונות לשמור נתונים על נקודות גיאוגרפיות

3.1. אובייקט קו רוחב

PUT index_name / index_type / 1 {"location": {"lat": 23.02, "lon": 72.57}}

הנה, גיא-פוינט מקום נשמר כאובייקט עם קו רוחב ו קו אורך כמפתחות.

3.2. זוג קו רוחב

{"מיקום": "23.02,72.57"}

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

3.3. גיאו האש

{"location": "tsj4bys"}

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

3.4. מערך קו רוחב אורך

{"מיקום": [72.57, 23.02]}

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

4. דרכים שונות לשמירת נתוני צורה גיאוגרפית

4.1. נְקוּדָה

POST / אינדקס / סוג {"מיקום": {"סוג": "נקודה", "קואורדינטות": [72.57, 23.02]}}

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

4.2. LineString

POST / index / type {"location": {"type": "linestring", "coordinates": [[77.57, 23.02], [77.59, 23.05]]}}

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

4.3. מְצוּלָע

POST / אינדקס / סוג {"מיקום": {"סוג": "מצולע", "קואורדינטות": [[[10.0, 0.0], [11.0, 0.0], [11.0, 1.0], [10.0, 1.0], [ 10.0, 0.0]]]}}

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

Elasticsearch תומך גם במבנים אחרים של GeoJSON. רשימה מלאה של פורמטים נתמכים אחרים היא להלן:

  • MultiPoint
  • MultiLineString
  • מולטי פוליגון
  • GeometryCollection
  • מַעֲטָפָה
  • מעגל

אנו יכולים למצוא דוגמאות לפורמטים הנתמכים לעיל באתר הרשמי של ES.

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

5. שאילתת גיאוגרפיה של ElasticSearch

עכשיו, כשאנחנו יודעים להוסיף מסמכים המכילים צורות גיאוגרפיות, בואו נצלול להביא את הרשומות האלה באמצעות שאילתות צורות גיאוגרפיות. אך לפני שנתחיל להשתמש בשאילתות גיאוגרפיות, נצטרך תלות בבינה הבאה כדי לתמוך ב- Java API עבור שאילתות גיאוגרפיות:

 org.locationtech.spatial4j spatial4j 0.7 com.vividsolutions jts 1.13 xerces xercesImpl 

אנו יכולים לחפש את התלות שלעיל גם במאגר Maven Central.

Elasticsearch תומך בסוגים שונים של שאילתות גיאוגרפיות והם כדלקמן:

5.1. שאילתת צורה גיאוגרפית

זה דורש את גיאוגרפיה מיפוי.

דומה ל גיאוגרפיה סוּג, גיאוגרפיה משתמש במבנה GeoJSON לשאילתת מסמכים.

להלן שאילתת דוגמה להבאת כל המסמכים שנפלו בְּתוֹך נתון קואורדינטות עליון שמאלה ותחתונה מימין:

{"query": {"bool": {"must": {"match_all": {}}, "filter": {"geo_shape": {"region": {"shape": {"type": "envelope "," קואורדינטות ": [[75.00, 25.0], [80.1, 30.2]]}," relation ":" בתוך "}}}}}

פה, יַחַס קובע מפעילי קשר מרחבי משמש בזמן החיפוש.

להלן רשימת המפעילים הנתמכים:

  • אינטרקציות - (ברירת מחדל) מחזירה את כל המסמכים ש- גיאוגרפיה שדה חוצה את הגיאומטריה של השאילתה
  • אכזבה - מאחזר את כל המסמכים אשר גיאוגרפיה לשדה אין שום דבר במשותף עם הגיאומטריה של השאילתה
  • בְּתוֹך - מקבל את כל המסמכים שלהם גיאוגרפיה השדה נמצא בגיאומטריית השאילתה
  • מכיל - מחזיר את כל המסמכים שלהם גיאוגרפיה שדה מכיל את הגיאומטריה של השאילתה

באופן דומה, אנו יכולים לשאול באמצעות צורות GeoJSON שונות.

קוד Java לשאילתה לעיל הוא להלן:

קואורדינטות topLeft = קואורדינטות חדשות (74, 31.2); קואורדינטות bottomRight = קואורדינטות חדשות (81.1, 24); GeoShapeQueryBuilder qb = QueryBuilders.geoShapeQuery ("אזור", EnvelopeBuilder חדש (topLeft, bottomRight) .buildGeometry ()); qb.relation (ShapeRelation.INTERSECTS);

5.2. שאילתת תיבות גיאוגרפיות

שאילתת Geo Bounding Box משמשת לאיסוף כל המסמכים על בסיס מיקום נקודה. להלן דוגמה לשאילתת תיבה תוחמת:

{"query": {"bool": {"must": {"match_all": {}}, "filter": {"geo_bounding_box": {"location": {"left_left": [28.3, 30.5], " top_right ": [31.8, 32.12]}}}}}

קוד Java לשאילתת תיבה תחומה הוא כמפורט להלן:

QueryBuilders .geoBoundingBoxQuery ("מיקום"). SetCorners (31.8, 30.5, 28.3, 32.12);

שאילתת Geo Bounding Box תומכת בפורמטים דומים כמו שיש לנו geo_point סוג מידע. שאילתות לדוגמא לפורמטים נתמכים ניתן למצוא באתר הרשמי.

5.3. שאילתת מרחק גיאוגרפי

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

הנה דוגמא מרחק גיאוגרפי שאילתא:

{"query": {"bool": {"must": {"match_all": {}}, "filter": {"geo_distance": {"distance": "10miles", "location": [31.131,29.976 ]}}}}}

והנה קוד Java לשאילתה לעיל:

QueryBuilders .geoDistanceQuery ("מיקום"). נקודה (29.976, 31.131) .distance (10, DistanceUnit.MILES);

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

5.4. גיאוגרפי מְצוּלָע שאילתא

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

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

{"query": {"bool": {"must": {"match_all": {}}, "filter": {"geo_polygon": {"location": {"points": [{"lat": 22.733 , "lon": 68.859}, {"lat": 24.733, "lon": 68.859}, {"lat": 23, "lon": 70.859}]}}}}}

ובקוד Java עבור שאילתה זו:

רשימת allPoints = ArrayList חדש (); allPoints.add (GeoPoint חדש (22.733, 68.859)); allPoints.add (GeoPoint חדש (24.733, 68.859)); allPoints.add (GeoPoint חדש (23, 70.859)); QueryBuilders.geoPolygonQuery ("מיקום", allPoints);

שאילתת מצולעים גיאוגרפיים תומכת גם בפורמטים המוזכרים להלן:

  • lat-long כמו מערך: [lon, lat]
  • lat-long כמו מחרוזת: "lat, lon"
  • חשיש גיאוגרפי

geo_point סוג נתונים הוא חובה על מנת להשתמש בשאילתה זו.

6. מסקנה

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

עברנו גם דרכים שונות לאחסון נתונים גיאוגרפיים ולבסוף, ראינו שאילתות גיאוגרפיות ו- Java API כדי לסנן תוצאות באמצעות שאילתות גיאוגרפיות.

כמו תמיד, הקוד זמין בפרויקט GitHub זה.


$config[zx-auto] not found$config[zx-overlay] not found