ElasticsearchCRUD使用(十三)【Elasticsearch谷歌地图搜索的MVC应用】
本文介紹如何創建一個使用谷歌地圖和Elasticsearch的MVC應用程序進行geo_distance搜索,并找到最近的點(文檔)到您的位置。
Elasticsearch索引使用geo_point來定義每個文檔的位置。Elasticsearch支持GeoJson格式。
Elasticsearch索引和類型使用以下模型創建:
public class MapDetail {public long Id { get; set; }public string Name { get; set; }public string Details { get; set; }public string Information { get; set; }public string DetailsType { get; set; }[ElasticsearchGeoPoint]public GeoPoint DetailsCoordinates { get; set; } }DetailsCoordinates屬性使用GeoPoint類,用于geo_distance搜索。 Elasticsearch中的映射使用ElasticsearchCRUD的IndexCreate方法創建。 Elasticsearch中的Geo類型如果是geo_point,則需要一個ElasticsearchGeoPoint屬性,如果它是一個shape 類型,則需要一個ElasticsearchGeoShape屬性。 必須映射Geo屬性,并在索引新文檔時不能自動創建。
public void InitMapDetailMapping() {using (var context = new ElasticsearchContext(ConnectionString, new ElasticsearchSerializerConfiguration(_elasticsearchMappingResolver))){context.TraceProvider = new ConsoleTraceProvider();context.IndexCreate<MapDetail>();} }可以使用以下方式查看映射:
http://localhost:9200/_mapping一旦創建了索引和類型,就會使用_bulk API添加一些數據。 這些文件都使用SaveChanges()方法發送。
public void AddMapDetailData() {var dotNetGroup = new MapDetail { DetailsCoordinates = new GeoPoint(7.47348, 46.95404), Id = 1, Name = ".NET User Group Bern", Details = "http://www.dnug-bern.ch/", DetailsType = "Work" };var dieci = new MapDetail { DetailsCoordinates = new GeoPoint(7.41148, 46.94450), Id = 2, Name = "Dieci Pizzakurier Bern", Details = "http://www.dieci.ch", DetailsType = "Pizza" };var babylonKoeniz = new MapDetail { DetailsCoordinates = new GeoPoint(7.41635, 46.92737), Id = 3, Name = "PIZZERIA BABYLON K?niz", Details = "http://www.pizza-babylon.ch/home-k.html", DetailsType = "Pizza" };var babylonOstermundigen = new MapDetail { DetailsCoordinates = new GeoPoint(7.48256, 46.95578), Id = 4, Name = "PIZZERIA BABYLON Ostermundigen", Details = "http://www.pizza-babylon.ch/home-o.html", DetailsType = "Pizza" };using (var context = new ElasticsearchContext(ConnectionString, new ElasticsearchSerializerConfiguration(_elasticsearchMappingResolver))){context.TraceProvider = new ConsoleTraceProvider();context.AddUpdateDocument(dotNetGroup, dotNetGroup.Id);context.AddUpdateDocument(dieci, dieci.Id);context.AddUpdateDocument(babylonKoeniz, babylonKoeniz.Id);context.AddUpdateDocument(babylonOstermundigen, babylonOstermundigen.Id);context.SaveChanges();} }Elasticsearch中的索引和類型在global.asax Application_Start方法中初始化。 這將檢查索引是否存在,并創建一個新的索引(如果沒有)。
private void InitSearchEngine() {var searchProvider = new SearchProvider();if (!searchProvider.MapDetailsIndexExists()){searchProvider.InitMapDetailMapping();searchProvider.AddMapDetailData();} }使用geo_distance filter 和 query查詢索引。 這將搜索最大距離內的所有文檔,并從最接近您的搜索位置的升序排序命中結果。
{"query" :{"filtered" : {"query" : {"match_all" : {}},"filter" : {"geo_distance" : {"distance" : "300m","detailscoordinates" : [7.41148,46.9445]}}}},"sort" : [{"_geo_distance" : {"detailscoordinates" : [7.41148,46.9445],"order" : "asc","unit" : "m"}}]} }上面的Elasticsearch 查詢看起來像這樣在C#
var search = new Search {Query = new Query(new Filtered( new Filter(new GeoDistanceFilter( "detailscoordinates", new GeoPoint(centerLongitude, centerLatitude), new DistanceUnitMeter(maxDistanceInMeter)))){Query = new Query(new MatchAllQuery())}),Sort = new SortHolder(new List<ISort>{new SortGeoDistance("detailscoordinates", DistanceUnitEnum.m){Order = OrderEnum.asc}}) };然后在HomeController中使用它,如下所示:
public ActionResult Search(int maxDistanceInMeter, double centerLongitude, double centerLatitude) {var searchResult = _searchProvider.SearchForClosest(maxDistanceInMeter, centerLongitude, centerLatitude);var mapModel = new MapModel{MapData = new JavaScriptSerializer().Serialize(searchResult),CenterLongitude = centerLongitude,CenterLatitude = centerLatitude,MaxDistanceInMeter = maxDistanceInMeter};return View("Index", mapModel); }razor 索引視圖使用此數據在地圖顯示中。 使用綠色圖像顯示與您的搜索位置最接近的文檔。 最大搜索距離內的所有命中也顯示在地圖中。 您可以移動您的中心位置,增加或減少最大允許距離,結果將被正確顯示。
@*Bern Lat 46.94792, Long 7.44461 *@ @model WebAppGeoElasticsearch.Models.MapModel<input type="hidden" value="@Model.MapData" id="mapdata" name="mapdata" />@using (Html.BeginForm("Search", "Home")) {<fieldset class="form"><legend>SEARCH for closest document in the search engine using geo distance</legend><table width="800"><tr><th></th></tr><tr></tr><tr><td><input type="submit" value="Search fo closest: " style="width: 300px"></td><td><input type="hidden" value="@Model.CenterLongitude" id="centerLongitude" name="centerLongitude" /><input type="hidden" value="@Model.CenterLatitude" id="centerLatitude" name="centerLatitude" /></td><td><p style="width: 300px">Max distance in meter:</p><input id="maxDistanceInMeter" name="maxDistanceInMeter" type="text" title="" value="@Model.MaxDistanceInMeter" style="width: 200px" /></td></tr></table></fieldset>}<div class="row">@*Bern Lat 46.94792, Long 7.44461 *@<div id="googleMap" style="width: 1000px; height: 800px;"></div> </div>@section scripts {<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script><script type="text/javascript" src="http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markermanager/src/markermanager.js"></script><script language="javascript" type="text/javascript">var map;var mgr;function initialize() {var myOptions = {zoom: 13,center: new google.maps.LatLng(46.94792, 7.44461),mapTypeId: google.maps.MapTypeId.ROADMAP};map = new google.maps.Map(document.getElementById("googleMap"), myOptions);mgr = new MarkerManager(map);var infoWindow = new google.maps.InfoWindow({ content: "contents" });google.maps.event.addListener(mgr, 'loaded', function() {var modelData = $.parseJSON($("#mapdata").val());var first = true;$.each(modelData, function(entryIndex, entry) {//alert("Data" + entry.DetailsCoordinates + ", " + entry.Details);var htmlString = "<a href=\"" + entry.Details + "\">" + entry.Name + "</a>";var coor = entry.DetailsCoordinates.toString();var array = coor.split(',');// alert("Lat" + array[1] + "Long" + array[0]);if (first) {var marker = new google.maps.Marker({position: new google.maps.LatLng(array[1], array[0]),html: htmlString,icon: "http://localhost:2765/Content/yourposition.png"});first = false;} else {var marker = new google.maps.Marker({position: new google.maps.LatLng(array[1], array[0]),html: htmlString});}google.maps.event.addListener(marker, "click", function() {infoWindow.setContent(this.html);infoWindow.open(map, this);});mgr.addMarker(marker, 0);});// alert('homemarker: ' + $("#centerLatitude").val() + ' Current Lng: ' + $("#centerLongitude").val());var homemarker = new google.maps.Marker({position: new google.maps.LatLng($("#centerLatitude").val(), $("#centerLongitude").val()),html: "YOU",draggable: true,icon: "http://localhost:2765/Content/ort.png"});google.maps.event.addListener(homemarker, 'dragend', function(evt) {// alert('Marker dropped: Current Lat: ' + evt.latLng.lat().toFixed(3) + ' Current Lng: ' + evt.latLng.lng().toFixed(3));$("#centerLongitude").val(evt.latLng.lng().toFixed(3));$("#centerLatitude").val(evt.latLng.lat().toFixed(3));});mgr.addMarker(homemarker, 0);mgr.refresh();});}google.maps.event.addDomListener(window, 'load', initialize);</script> }搜索后的應用程序視圖:
結論
您可以看到,使用Elasticsearch進行Geo搜索很容易。 支持一系列Geo搜索過濾器,地理邊界框過濾器,地理距離過濾器,地理距離范圍過濾器,地理多邊形過濾器,GeoShape過濾器,Geohash信元過濾器(Geo Bounding Box Filter, Geo Distance Filter, Geo Distance Range Filter, Geo Polygon Filter, GeoShape Filter, Geohash Cell Filter)以及大多數geoJSON形狀和GeoShape查詢。 可以創建最優搜索以匹配大多數要求。
總結
以上是生活随笔為你收集整理的ElasticsearchCRUD使用(十三)【Elasticsearch谷歌地图搜索的MVC应用】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: EDA数据增强
- 下一篇: 解决IDEA连接mysql时出现Serv