ElasticsearchCRUD使用(十三)【Elasticsearch谷歌地图搜索的MVC应用】
来源:互联网 发布:阴司守门人网络剧资源 编辑:程序博客网 时间:2024/06/08 03:05
本文介绍如何创建一个使用谷歌地图和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应用】
- ElasticsearchCRUD使用(六)【EF和Elasticsearch的MVC应用程序】
- ElasticsearchCRUD使用(十)【Elasticsearch类型与ElasticsearchCRUD的映射】
- ElasticsearchCRUD使用(十二)【Elasticsearch的German分析器】
- ElasticsearchCRUD使用(十八)【进行MVC搜索Elasticsearch高亮】
- ElasticsearchCRUD使用(三)【嵌套文档的MVC】
- ElasticsearchCRUD使用(十六)【Elasticsearch聚合】
- ElasticsearchCRUD使用(十一)【Elasticsearch同义词分析器】
- ElasticsearchCRUD使用(四)【使用EF从SQLServer到Elasticsearch的数据传输】
- ElasticsearchCRUD使用(八)【使用Elasticsearch和WebAPI导出CSV】
- ElasticsearchCRUD使用(二)【简单的文档进行搜索的MVC应用程序】
- ElasticsearchCRUD使用(五)【Elasticsearch中的子文档,父文档】
- ElasticsearchCRUD使用(七)【Elasticsearch中的实时重建索引】
- ElasticsearchCRUD使用(九)【Elasticsearch父子,孙子节点文件和路由】
- ElasticsearchCRUD使用(十七)【Elasticsearch搜索多个指标和类型】
- ElasticsearchCRUD使用(一)【介绍】
- google api 地图搜索应用
- ElasticsearchCRUD使用(十九)【索引热身】
- jfinal编码问题及解决
- OpenGL ES
- ListView2——Android群英传
- 51nod 1208 && POJ 2482:Stars in Your Window【普通线段树】
- 虚指针的对齐_boolan_第二门课_第一周_作业
- ElasticsearchCRUD使用(十三)【Elasticsearch谷歌地图搜索的MVC应用】
- linux上ActiveMQ 集群安装、配置和高可用测试
- 选择排序算法
- ROS多机通信
- You-Dont-Know-JS
- HBuilder连接夜神模拟器
- Ubutu 17.04 WiFi热点创建
- J.U.C — Collections — CopyOnWrite****
- String StringBuffer StringBuilder