قدمت المقالة السابقة أن Elasticsearch يستخدم المستودع و ElasticsearchTemplate لإنشاء ظروف استعلام معقدة ، وتقدم بإيجاز وظيفة Elasticsearch لاستخدام الموقع الجغرافي.
في هذه المقالة ، دعونا نلقي نظرة على وظيفة استخدام Elasticsearch لإكمال استعلام البيانات الكبير القريب والبحث عن البيانات ضمن نطاق N-Meter.
إعداد البيئة
يستخدم الاختبار الأصلي أحدث إصدار Elasticsearch 5.5.1 و Springboot1.5.4 و Spring-Data-Elasticsearch2.1.4.
قم بإنشاء مشروع Springboot جديد ، والتحقق من Elasticsearch و Web.
ملف POM كما يلي
<؟ XSI: schemalocation = "http://maven.apache.org/pom/4.0.0 <soph> 0.0.1-snapshot </version> <packaging> جرة </packaging> <name> elasticsearch </name> <description> مشروع تجريبي لـ Spring Boot </descriver <!-Lookup Parent from ropository-> </paret> <properties> <project.build.sourceencoding> utf-8 </project.build.sourceencoding> <project.reporting.outputencoding> utf-8 </project.reporting.utputencoding> <ependencies> <Rependency> <roupiD> org.springframework.boot </rougiD> <StifactId> Spring-boot-starter-data-elasticsearch </intifactid> </redenced> <redenced> <roupeid> org.springframework.boot </groupid> <Rependency> <roupeD> org.springframework.boot </rougiD> <intifactid> Spring-Boot-Starter-Test </shintifactid> <scope> test </scope> </redepency> <sperency> <supensid> com.sun.jna </groupid> </sependencies> <build> <ultionins> <clupin> <roupiD> org.springframework.boot </rougiD> <ChintifactId> Spring-Boot-Maven-Plugin </suntifactid> </sultcin> </sultcins> </build> </project>
إنشاء شخص فئة نموذجية جديدة
حزمة com.tianyalei.elasticsearch.model ؛ استيراد org.springframework.data.annotation.id ؛ استيراد org.springframework.data.elasticsearch.annotations.document ؛ استيراد org.springframework.data.elasticsearch.annotations.geopointfield ؛ استيراد java.io.serializable ؛ / *** فئة النموذج*/ document (indexName = "lext_search_project" ، type = "person" ، indexStorEtype = "FS" ، shards = 5 ، remlicas = 1 ، refreshinterval = "-1") profire profermance profiremable {id private private id ؛ اسم السلسلة الخاصة ؛ سلسلة سلسلة خاصة ؛ / ** * خط العرض الجغرافي وخط الطول * خط العرض ، خط الطول LON "40.715 ، -74.011" * إذا كنت تستخدم صفيفًا ، فإن العكس صحيح [-73.983 ، 40.719] */ GeOpointfield Private String العنوان ؛ public int getId () {return id ؛ } public void setId (int id) {this.id = id ؛ } السلسلة العامة getName () {return name ؛ } public void setName (اسم السلسلة) {this.name = name ؛ } السلسلة العامة getPhone () {return phone ؛ } public void setphone (سلسلة الهاتف) {this.phone = phone ؛ } السلسلة العامة getAddress () {return address ؛ } public void setAddress (عنوان السلسلة) {this.address = العنوان ؛ }} يمكنني استخدام حقل العنوان لتمثيل وضع خط الطول والخطوط. لاحظ أن استخدام String [] و string مختلفان عند الإشارة إلى خط العرض وخط الطول ، راجع التعليقات.
استيراد com.tianyalei.elasticsearch.model.person ؛ استيراد org.springframework.data.elasticsearch.repository.elasticsearchRepository ؛ الواجهة العامة personrepository يمتد ElasticsearchRepository <شخص ، integer> {} ألقِ نظرة على فئة الخدمة وأكمل وظيفة إدراج بيانات الاختبار. أضع وظيفة الاستعلام في وحدة التحكم. من أجل الراحة ، يجب وضعها في الخدمة بشكل طبيعي.
حزمة com.tianyalei.elasticsearch.service ؛ استيراد com.tianyalei.elasticsearch.model.person ؛ استيراد com.tianyalei.elasticsearch.repository.personRepository ؛ استيراد org.springframework.beans.factory.annotation.autowired ؛ استيراد org.springframework.data.elasticsearch.core.elasticsearchTemplate ؛ استيراد org.springframework.data.elasticsearch.core.query.indexquery ؛ استيراد org.springframework.stereotype.service ؛ استيراد java.util.arraylist ؛ استيراد java.util.list ؛ service public class propernervice {Autowired personRepository personRepository ؛ @autowired elasticsearchtemplate elasticsearchTemplate ؛ Static Final String person_index_name = "lext_search_project" ؛ Static Final String Person_index_type = "person" ؛ الشخص العام يضيف (شخص) {return personrepository.save (شخص) ؛ } public void bulkindex (قائمة <Person> personlist) {int counter = 0 ؛ حاول {if (! elasticsearchTemplate.indexexists (person_index_name)) {elasticsearchTemplate.createIndex (person_index_type) ؛ } list <Sexquery> Queries = new ArrayList <> () ؛ لـ (الشخص الشخص: personlist) {indexquery indexquery = new indexQuery () ؛ indexquery.setId (person.getId () + "") ؛ indexquery.setObject (الشخص) ؛ indexquery.setIndExName (person_index_name) ؛ indexquery.settype (person_index_type) ؛ // يمكن أيضًا استخدام الخطوات المذكورة أعلاه للبناء باستخدام indexQueryBuilder // indexquery index = indexquerybuilder () Queries.Add (indexquery) ؛ if (counter ٪ 500 == 0) {elasticsearchtemplate.bulkindex (Queries) ؛ Queries.clear () ؛ System.out.println ("عداد BulkIndex:" + عداد) ؛ } counter ++ ؛ } if (Queries.size ()> 0) {elasticsearchTemplate.Bulkindex (Queries) ؛ } system.out.println ("الانتهاء من bulkindex.") ؛ } catch (استثناء e) {system.out.println ("مفهرس service.bulkindex e ؛" + e.getMessage ()) ؛ رمي ه ؛ }}}انتبه إلى طريقة BulkIndex ، والتي يتم استخدامها لدعم بيانات إدراج. الجزء الأكبر هو أيضًا طريقة إدراج الدُفعات الموصى بها رسميًا من قبل ES. هنا ، يتم إدخال الجزء الأكبر من كل 500 مضاعفات عدد صحيح.
حزمة com.tianyalei.elasticsearch.controller ؛ استيراد com.tianyalei.elasticsearch.model.person ؛ استيراد com.tianyalei.elasticsearch.service.personservice ؛ استيراد org.elasticsearch.common.unit.distanceUnit ؛ استيراد org.elasticsearch.index.query.geodistanceQueryBuilder ؛ استيراد org.elasticsearch.index.query.querybuilders ؛ استيراد org.elasticsearch.search.sort.geodistancesortbuilder ؛ استيراد org.elasticsearch.search.sort.sortbuilders ؛ استيراد org.elasticsearch.search.sort.sortorder ؛ استيراد org.springframework.beans.factory.annotation.autowired ؛ استيراد org.springframework.data.domain.pagerequest ؛ استيراد org.springframework.data.domain.pagable ؛ استيراد org.springframework.data.elasticsearch.core.elasticsearchTemplate ؛ استيراد org.springframework.data.elasticsearch.core.query.nativeSearchQueryBuilder ؛ استيراد org.springframework.data.elasticsearch.core.query.searchquery ؛ استيراد org.springframework.web.bind.annotation.getMapping ؛ استيراد org.springframework.web.bind.annotation.restController ؛ استيراد java.text.decimalformat ؛ استيراد java.util.arraylist ؛ استيراد java.util.list ؛ استيراد java.util.random ؛ RestController الفئة العامة PersonController {Autowired PersonService @autowired elasticsearchtemplate elasticsearchTemplate ؛ getMapping ("/add") كائن عام add () {double lat = 39.929986 ؛ مزدوج LON = 116.395645 ؛ قائمة <Person> personlist = new ArrayList <> (900000) ؛ لـ (int i = 100000 ؛ i <1000000 ؛ i ++) {double max = 0.00001 ؛ min double = 0.000001 ؛ عشوائي عشوائي = جديد عشوائي () ؛ double s = random.nextDouble () ٪ (max - min + 1) + max ؛ decimalformat df = new decimalformat ("###### 0.000000") ؛ // system.out.println (s) ؛ سلسلة lons = df.format (s + lon) ؛ سلسلة lats = df.format (s + lat) ؛ double dlon = double.valueof (lons) ؛ double dlat = double.valueof (lats) ؛ شخص الشخص = شخص جديد () ؛ person.setid (i) ؛ person.setName ("name" + i) ؛ person.setPhone ("tel" + i) ؛ person.setAddress (dlat + "،" + dlon) ؛ personlist.add (شخص) ؛ } profonservice.bulkindex (personlist) ؛ // searchquery searchquery = new NatistsearchQueryBuilder (). withQuery (querybuilders.querystringQuery ("spring boot أو book"). build () ؛ // list <article> المقالات = elas ، ticsearchtemplate.queryForList (SE ، Archquery ، article.class) ؛ // for (المقالة المقالة: المقالات) {// system.out.println (article.toString ()) ؛ //} إرجاع "إضافة البيانات" ؛ } /*** geo_distance: ابحث عن الموقع ضمن نطاق معين من نقطة مركزية معينة geo_bounding_box: ابحث عن الموقع داخل منطقة مستطيل geo_distance_range: ابحث عن الموقع بين min و max geo_polygon: ابحث عن الموقع داخل مادة متعددة. يمكن استخدام الفرز لفرز */ getMapping ("/ query") Query Query () {double lat = 39.929986 ؛ مزدوج LON = 116.395645 ؛ long nowtime = system.currentTimeMillis () ؛ // الاستعلام ضمن خط عرض وعطامة معينة في حدود 100 متر. GeodistanceQueryBuilder Builder = QueryBuilders.GeodistanceQuery ("العنوان"). النقطة (LAT ، LON). geodistancesortbuilder sortbuilder = sortbuilders.geodistancesort ("العنوان"). قابلة للباحة قابلة للباحة = جديد pagerequest (0 ، 50) ؛ natistsearchquerybuilder builder1 = New NatistsearchQueryBuilder (). withFilter (builder). withsort (sortbuilder). مع قابلة للبلاط (قابلة للبناء) ؛ SearchQuery SearchQuery = builder1.build () ؛ // QueryForList تم توضيحه افتراضيًا ، ويتم استخدام QueryForpage. الافتراضي هو 10 قائمة <Pirons> personlist = elasticsearchtemplate.queryForList (SearchQuery ، person.class) ؛ System.out.println ("timeconsuming:" + (System.CurrentTimeMillis () - Nowtime)) ؛ إرجاع قائمة الشخص ؛ }} بالنظر إلى فئة وحدة التحكم ، في طريقة إضافة ، نقوم بإدراج 900000 بيانات اختبار وننشئ عناوين خطوط الطول والعناصر المختلفة بشكل عشوائي.
في طريقة الاستعلام ، نقوم ببناء حالة استعلام على بعد 100 متر من الاستعلام ، وفرزها وفقًا للمسافة ، وترحيل 50 عنصرًا لكل صفحة. إذا لم يتم تحديد قابلة للبلاغ ، فإن QueryForlist of EspecteMate هو 10 بشكل افتراضي ، والذي يمكن رؤيته من خلال الكود المصدري.
ابدأ تشغيل المشروع ، وقم بتنفيذ الإضافة أولاً ، وانتظر إدراج ملايين البيانات ، لمدة بضع عشرات ثانية تقريبًا.
ثم قم بتنفيذ الاستعلام وشاهد النتائج.
استغرق الاستعلام الأول أكثر من 300 مللي ثانية ، وانخفض الوقت بشكل كبير بعد الاستعلام مرة أخرى ، إلى حوالي 30 مللي ثانية ، لأنه تم تخزين ES تلقائيًا إلى الذاكرة.
يمكن ملاحظة أن ES تكمل استعلام الموقع الجغرافي بسرعة كبيرة. مناسبة للاستعلامات مثل الأشخاص القريبين والاستعلام النطاق.
PostScript: في الاستخدام لاحقًا ، في الإصدار 2.3 Elasticsearch ، لا يمكن فهرسة النمط الجغرافي وفقًا لطريقة الكتابة أعلاه. إدخال ES هو سلسلة بدلا من الجيوفيل العلامة. فيما يلي سجل للحل ، وقم بتعديل نوع السلسلة إلى Geopoint ، ويتم تعبئته تحت org.springframework.data.elasticsearch.core.geo.geopoint. ثم تحتاج إلى استدعاء طريقة التعيين بشكل صريح عند إنشاء الفهرس لخريطة خريطة بشكل صحيح إلى Geofield.
على النحو التالي
if (! elasticsearchTemplate.IndExexists ("ABC")) {elasticsearchTemplate.CreateIndex ("ABC") ؛ ElasticsearchTemplate.putMapping (person.class) ؛ }ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.