ES地理范围查询第二讲:地理位置信息之geo_shape

1.前言

在前面我简单的介绍了es对地理位置点的相关操作,包括获取多边形内(凸多边形)的点及计算两点之间的距离,或者按照距离的远近排序的简要查询方法,但是假如我们的想要查询落在一个凹多边形内的点,使用geo_point类型的就满足不了我们的需求了,这时候es引入了geo_shape类型。

2. Geo_shape

geo_shape支持GeoJsonWKT(Well-Known Text,==6.X以后的版本支持==)格式的形状,
一个典型的GeoJson表示的点:

{
    "type": "Point",
    "coordinates": [125.6, 10.1]
  }

一个典型的用WKT表示的点:

POINT(125.6 10.1)

详细介绍,基于支持的这些形状,我们可以实现更加复杂的查询,包括多边形(矩形、圆形、多边形等)内的点,多边形的相交,直线等等;

3. 业务场景

获取一个城市地理范围(不规则)内的坐标点。一个典型的不规则的城市地理位置的坐标形式如下(WKT):

MULTIPOLYGON(((110.390839 24.038563,110.392876 24.035597,110.393425 24.030552,110.393707 24.027109,110.393997 24.023668,110.393539 24.01976,110.391083 24.014458,110.38887 24.01053,110.386658 24.00638,110.384613 23.999998,110.386757 23.991854,110.388741 23.986572,110.389236 23.985193,110.39122 23.981291,110.392174 23.972574,110.391907 23.967531,110.389359 23.958139,110.38356 23.948992,110.375526 23.942373,110.36451 23.938519,110.358002 23.936707,110.354736 23.934425,110.349701 23.924356,110.347908 23.915421,110.348373 23.907164,110.348839 23.900513,110.352562 23.89385,110.360031 23.888321,110.367767 23.885538,110.374512 23.884136,110.378258 23.883665,110.386497 23.882486,110.394241 23.881083,110.398972 23.877165,110.402451 23.873713,110.403931 23.869577,110.406914 23.865669,110.412651 23.8645,110.418404 23.865852,110.421913 23.866066,110.425659 23.866968,110.429161 23.868328,110.43541 23.868761,110.439148 23.866684,110.441383 23.864155,110.446114 23.858171,110.449089 23.854948,110.451569 23.852413,110.455063 23.850796,110.458557 23.851467,110.462067 23.85306,110.466583 23.855103,110.471077 23.85623,110.472816 23.855534,110.475807 23.853914,110.479309 23.852297,110.482803 23.850445,110.488502 23.844,110.487984 23.840336,110.485474 23.838053,110.484222 23.83691,110.48246 23.835314,110.480438 23.831194,110.481667 23.827291,110.483398 23.824303,110.495049 23.807512,110.498528 23.804516,110.506523 23.802645,110.518013 23.803049,110.528763 23.805981,110.535027 23.810995,110.539307 23.81625,110.541847 23.821966,110.545631 23.828833,110.549141 23.830875,110.553627 23.829021,110.556358 23.825798,110.559822 23.820505,110.561813 23.818432,110.565521 23.812681,110.567253 23.809004,110.567734 23.806479,110.567451 23.801434,110.567703 23.800289,110.568176 23.798681,110.574387 23.792688,110.575394 23.791996,110.577873 23.78923,110.57785 23.786251,110.576088 23.783276,110.574821 23.780533,110.56472 23.762697,110.562447 23.759727,110.557167 23.753101,110.552902 23.748997,110.548126 23.74489,110.545868 23.741232,110.545341 23.736879,110.550056 23.731123,110.552544 23.728588,110.557503 23.724438,110.56221 23.718452,110.565666 23.712015,110.567383 23.706961,110.568604 23.701908,110.568077 23.697784,110.567307 23.695723,110.566803 23.692514,110.56752 23.688385,110.568253 23.68586,110.570969 23.680342,110.56794 23.674852,110.560188 23.672369,110.553192 23.670338,110.547211 23.672203,110.543213 23.669699,110.541183 23.663975,110.542877 23.656628,110.547348 23.652479,110.550331 23.65086,110.562531 23.646671,110.570717 23.640669,110.577927 23.634441,110.583366 23.626846,110.587059 23.61857,110.585533 23.613764,110.582764 23.610336,110.580498 23.606449,110.578979 23.602329,110.580437 23.596588,110.589127 23.591042,110.593857 23.588953,110.601051 23.582495,110.605019 23.578573,110.607727 23.574432,110.610687 23.569601,110.614143 23.562473,110.614349 23.556278,110.612343 23.552391,110.610809 23.548504,110.610031 23.543688,110.610764 23.539328,110.611992 23.537254,110.613922 23.527842,110.615356 23.517975,110.615311 23.510406,110.615257 23.503069,110.62043 23.492491,110.626373 23.486036,110.627586 23.482361,110.628563 23.476851,110.627274 23.471811,110.624763 23.469303,110.617752 23.463146,110.612 23.460655,110.609009 23.46044,110.602013 23.456577,110.596283 23.455688,110.589546 23.455267,110.584534 23.451162,110.581512 23.446133,110.580254 23.44178,110.581207 23.43696,110.58316 23.430529,110.581886 23.426405,110.578362 23.419769,110.577347 23.417253,110.570511 23.397566,110.567978 23.390236,110.565437 23.384056,110.563911 23.377182,110.564392 23.374886,110.565872 23.372126,110.570084 23.368435,110.576286 23.365194,110.581459 23.355305,110.58017 23.348431,110.579391 23.342699,110.579369 23.339029,110.583321 23.333736,110.589287 23.333015,110.618607 23.323231,110.633034 23.322237,110.646202 23.317806,110.652123 23.310436,110.65477 23.296886,110.652924 23.280611,110.651901 23.276489,110.650101 23.267782,110.647797 23.259308,110.643547 23.254744,110.637306 23.251104,110.631813 23.247696,110.626808 23.244282,110.62429 23.239479,110.623009 23.233292,110.619743 23.228493,110.612999 23.224628,110.609001 23.221897,110.598534 23.217133,110.590317 23.217863,110.582878 23.220196,110.577667 23.224581,110.573463 23.226665,110.570976 23.227365,110.568497 23.227837,110.564758 23.227167,110.561256 23.224892,110.545753 23.210974,110.541496 23.20503,110.539726 23.202057,110.539436 23.194031,110.543114 23.183922,110.548027 23.173344,110.549469 23.165768,110.548187 23.15843,110.546173 23.153627,110.5439 23.147902,110.54287 23.14171,110.543579 23.136433,110.543556 23.133224,110.543053 23.129095,110.538277 23.126188,110.532059 23.124153,110.52607 23.121201,110.523079 23.11961,110.51683 23.114365,110.515297 23.108635,110.514267 23.102219,110.504784 23.094921,110.497322 23.09404,110.493561 23.087402,110.494751 23.078451,110.494469 23.073404,110.487984 23.068619,110.482513 23.069332,110.473099 23.073502,110.462173 23.07332,110.451958 23.069696,110.445717 23.065365,110.434738 23.056234,110.427269 23.053514,110.424026 23.051922,110.416077 23.051954,110.413361 23.055864,110.406197 23.064842,110.39801 23.06625,110.392281 23.06352,110.387787 23.059641,110.379303 23.052334,110.373573 23.049372,110.366837 23.045498,110.361633 23.043913,110.355904 23.043016,110.351189 23.044641,110.346237 23.047178,110.34079 23.051102,110.337822 23.053864,110.333366 23.058699,110.328911 23.061926,110.326881 23.053446,110.326607 23.047022,110.326561 23.037846,110.324532 23.028221,110.32177 23.022724,110.314781 23.015636,110.309578 23.018867,110.301666 23.026464,110.2967 23.026484,110.290947 23.018702,110.290443 23.014114,110.29261 23.001492,110.296791 22.992531,110.296242 22.980146,110.289749 22.971909,110.281761 22.962299,110.272537 22.954762,110.264076 22.949512,110.255852 22.941734,110.254578 22.934858,110.255051 22.929354,110.259483 22.919016,110.260689 22.911442,110.259911 22.904329,110.260117 22.895844,110.260597 22.890106,110.262062 22.88345,110.263527 22.879541,110.265503 22.876554,110.265244 22.8738,110.263748 22.872435,110.25927 22.870152,110.24762 22.871565,110.238937 22.87228,110.230988 22.870008,110.227768 22.871624,110.228279 22.876671,110.228302 22.881258,110.227333 22.88608,110.227348 22.891127,110.224388 22.895264,110.217209 22.900791,110.212013 22.904705,110.20607 22.908163,110.197144 22.908876,110.185722 22.909369,110.175293 22.909855,110.160156 22.910124,110.147987 22.908319,110.139793 22.906046,110.133583 22.902849,110.126602 22.896671,110.121117 22.890949,110.115913 22.889814,110.113441 22.893492,110.111214 22.897163,110.108757 22.903824,110.107033 22.908875,110.10482 22.915991,110.101357 22.920816,110.095421 22.927023,110.091476 22.935062,110.088516 22.942181,110.083328 22.951366,110.082848 22.957102,110.079887 22.962156,110.073433 22.962856,110.06871 22.961029,110.066223 22.957825,110.062233 22.951637,110.057487 22.944998,110.051277 22.94409,110.04657 22.947081,110.04435 22.951443,110.040131 22.953745,110.036171 22.957191,110.03096 22.959497,110.023018 22.960657,110.016571 22.96319,110.0131 22.966639,110.010139 22.974215,110.008423 22.978117,110.005203 22.983398,109.998749 22.988226,109.991058 22.990763,109.979897 22.998808,109.971718 23.004784,109.96254 23.012596,109.954613 23.016737,109.944183 23.024778,109.936493 23.028688,109.9273 23.029844,109.918358 23.030313,109.909912 23.030783,109.898987 23.030106,109.890282 23.028048,109.883331 23.027826,109.883583 23.024614,109.879593 23.020262,109.876106 23.014528,109.870377 23.011091,109.86293 23.00559,109.855469 23.000093,109.847267 22.994133,109.838814 22.989321,109.834587 22.985195,109.828117 22.979464,109.821663 22.976942,109.812973 22.976948,109.805519 22.97718,109.798569 22.976725,109.797821 22.973055,109.801292 22.968006,109.806763 22.965483,109.815437 22.962725,109.81842 22.961805,109.820648 22.956757,109.820892 22.950792,109.823357 22.942532,109.826088 22.938173,109.831787 22.935644,109.836761 22.935184,109.839241 22.933577,109.837997 22.929218,109.835747 22.924633,109.836243 22.920961,109.841209 22.917974,109.845917 22.917055,109.851631 22.915445,109.855103 22.913149,109.857826 22.910166,109.856087 22.906954,109.85286 22.905809,109.846413 22.908108,109.839211 22.909948,109.831268 22.909723,109.826302 22.90835,109.826553 22.903992,109.832001 22.897104,109.835716 22.894121,109.842659 22.890219,109.847122 22.887691,109.852829 22.883556,109.857536 22.879654,109.859016 22.87644,109.85778 22.87392,109.852814 22.872545,109.843643 22.875992,109.832733 22.880819,109.82206 22.885181,109.814369 22.888626,109.809158 22.889547,109.804939 22.88863,109.803703 22.886108,109.802948 22.882439,109.805168 22.873949,109.802933 22.863855,109.801933 22.85858,109.800926 22.853306,109.798447 22.850552,109.792 22.851704,109.786789 22.85354,109.779846 22.859047,109.773399 22.860653,109.768181 22.858131,109.76123 22.85515,109.755524 22.85194,109.752792 22.846434,109.752037 22.839781,109.752289 22.833586,109.752281 22.827621,109.753021 22.821428,109.755249 22.812481,109.756241 22.806974,109.756233 22.80032,109.756233 22.794357,109.756722 22.787931,109.757462 22.782885,109.758209 22.779446,109.761177 22.774166,109.76638 22.76981,109.773323 22.766134,109.781013 22.763609,109.787209 22.762234,109.791924 22.758329,109.79216 22.755117,109.789429 22.751678,109.78199 22.748466,109.773552 22.745258,109.765617 22.742048,109.757439 22.739985,109.75 22.739527,109.74157 22.739985,109.734627 22.741821,109.729172 22.74205,109.724213 22.740213,109.720993 22.735395,109.71801 22.729891,109.715782 22.723696,109.716026 22.717272,109.718002 22.710159,109.718498 22.705112,109.716766 22.700066,109.70858 22.699373,109.697182 22.697079,109.690239 22.695242,109.682564 22.693174,109.677353 22.689732,109.669922 22.684223,109.666199 22.681009,109.663727 22.67642,109.660751 22.670683,109.658272 22.6677,109.655151 22.662489,109.652672 22.664783,109.650688 22.666388,109.647217 22.667763,109.641274 22.666157,109.632347 22.662477,109.622688 22.661324,109.616249 22.664074,109.613274 22.66843,109.610786 22.674166,109.608063 22.679213,109.610779 22.682426,109.613258 22.68656,109.612259 22.69482,109.60878 22.700327,109.604073 22.705374,109.601341 22.709499,109.589432 22.722342,109.582977 22.730597,109.58049 22.732429,109.577019 22.737476,109.573288 22.745733,109.572037 22.751242,109.570793 22.758123,109.568062 22.763859,109.562347 22.770508,109.555893 22.776009,109.551178 22.778988,109.542 22.780581,109.533821 22.779655,109.52961 22.777124,109.519691 22.775045,109.51001 22.777557,109.505791 22.783291,109.503052 22.790628,109.502541 22.798201,109.503769 22.804169,109.504997 22.807384,109.507973 22.813124,109.514168 22.81818,109.517883 22.82048,109.521111 22.822552,109.521851 22.824158,109.519119 22.826908,109.514664 22.825983,109.501747 22.825508,109.497276 22.829632,109.490334 22.835588,109.482384 22.836494,109.472473 22.835333,109.467247 22.836014,109.461037 22.84082,109.457802 22.847927,109.454811 22.852283,109.450592 22.855719,109.447357 22.858925,109.44635 22.866268,109.447578 22.871546,109.450302 22.874765,109.456749 22.8773,109.463203 22.878227,109.468163 22.879614,109.469902 22.880075,109.473869 22.882147,109.476837 22.88582,109.475838 22.890411,109.470863 22.896599,109.46167 22.900026,109.453972 22.902767,109.445534 22.905046,109.438812 22.910313,109.435333 22.913748,109.431107 22.915806,109.427139 22.914421,109.417717 22.908897,109.410767 22.908882,109.402069 22.914831,109.393112 22.922157,109.385887 22.929026,109.380669 22.934523,109.374687 22.940245,109.366966 22.949177,109.363243 22.95697,109.360229 22.96637,109.358467 22.974171,109.35347 22.986321,109.34848 22.993652,109.346237 22.995941,109.343498 22.999607,109.336029 23.005552,109.330307 23.007605,109.323097 23.008965,109.315643 23.01124,109.310417 23.012833,109.303703 23.017635,109.30368 23.024288,109.30864 23.028893,109.32402 23.037878,109.332947 23.044327,109.337646 23.048697,109.341347 23.057425,109.341072 23.069586,109.332817 23.089527,109.328331 23.094566,109.318382 23.097754,109.305206 23.095882,109.299248 23.0961,109.291283 23.099291,109.285553 23.104549,109.275101 23.106586,109.265419 23.103115,109.256973 23.10034,109.250267 23.099861,109.247017 23.104441,109.24649 23.11385,109.246193 23.127153,109.244186 23.133114,109.242432 23.138159,109.240913 23.147329,109.240387 23.150541,109.240143 23.154209,109.239357 23.160864,109.239349 23.166826,109.24205 23.175097,109.24453 23.179005,109.248993 23.183605,109.253937 23.188898,109.256912 23.194414,109.256897 23.199692,109.257133 23.204969,109.254112 23.213678,109.247124 23.221918,109.241867 23.229244,109.240837 23.23819,109.240822 23.243925,109.240799 23.25012,109.237793 23.258371,109.232788 23.264322,109.227539 23.2705,109.226021 23.278296,109.22699 23.284952,109.227219 23.290689,109.226707 23.294817,109.222954 23.301229,109.216721 23.304193,109.206017 23.30439,109.200546 23.301619,109.210953 23.314268,109.21492 23.31979,109.214127 23.330566,109.214363 23.336994,109.223297 23.341841,109.235992 23.344402,109.245941 23.348791,109.255379 23.357536,109.259087 23.363514,109.278473 23.379168,109.288399 23.389977,109.304039 23.405619,109.314217 23.415741,109.328407 23.421282,109.344856 23.419485,109.34935 23.417433,109.352852 23.410328,109.358093 23.40575,109.366333 23.403475,109.372063 23.39913,109.373573 23.391562,109.375343 23.386061,109.384552 23.384014,109.398743 23.388174,109.405724 23.384975,109.40947 23.379705,109.412483 23.372601,109.419952 23.368715,109.430908 23.371717,109.434883 23.375626,109.446327 23.383677,109.452301 23.386209,109.46376 23.385309,109.47123 23.384176,109.477966 23.378681,109.484207 23.372036,109.487709 23.363325,109.493057 23.354374,109.496986 23.346977,109.504791 23.336708,109.511848 23.331282,109.522774 23.323627,109.534027 23.317266,109.540573 23.312922,109.549026 23.311323,109.560226 23.311796,109.562973 23.314095,109.563217 23.318682,109.563332 23.325277,109.561447 23.331299,109.562447 23.33497,109.57003 23.354408,109.580048 23.367092,109.591911 23.370747,109.599564 23.375654,109.604065 23.379894,109.612213 23.387321,109.62191 23.399031,109.629868 23.411425,109.635597 23.421982,109.646057 23.42864,109.660751 23.429794,109.669983 23.425211,109.679192 23.416725,109.685173 23.410074,109.689163 23.406176,109.695892 23.404114,109.701622 23.40572,109.704613 23.407784,109.706596 23.408703,109.71183 23.415356,109.716812 23.420864,109.719803 23.426371,109.723541 23.438988,109.722542 23.447016,109.720299 23.451605,109.719299 23.459173,109.721298 23.462847,109.727524 23.465828,109.734253 23.465828,109.740982 23.463991,109.74572 23.464453,109.750687 23.4645,109.757919 23.46476,109.765633 23.467543,109.769363 23.469851,109.773323 23.475369,109.77626 23.486835,109.777992 23.489594,109.781471 23.49144,109.789703 23.491932,109.816628 23.487919,109.827103 23.487961,109.836823 23.485706,109.842346 23.474501,109.842819 23.473051,109.846413 23.471069,109.8479 23.469231,109.852379 23.463493,109.857361 23.460966,109.864853 23.465092,109.869827 23.470821,109.875572 23.479305,109.881561 23.484346,109.888313 23.493746,109.893051 23.506586,109.894318 23.521727,109.892593 23.531364,109.889847 23.539625,109.889122 23.556828,109.89138 23.567839,109.897881 23.580681,109.906372 23.588015,109.913368 23.59741,109.918129 23.611628,109.920639 23.623093,109.923401 23.637999,109.921432 23.655436,109.918701 23.667826,109.919724 23.680899,109.921471 23.684567,109.924217 23.687775,109.92672 23.68869,109.935707 23.68891,109.943199 23.690966,109.947708 23.701967,109.946983 23.712294,109.94899 23.725592,109.950737 23.728804,109.960487 23.734293,109.967491 23.73933,109.974747 23.74987,109.979523 23.762249,109.983032 23.771418,109.99279 23.779428,110.000793 23.781025,110.003029 23.780563,110.023521 23.78351,110.03727 23.788759,110.048523 23.795162,110.05703 23.799961,110.063782 23.803848,110.069542 23.810259,110.078568 23.822857,110.084839 23.831329,110.090103 23.835903,110.103867 23.847572,110.115646 23.858784,110.127693 23.872517,110.137451 23.880289,110.145714 23.88348,110.153214 23.881859,110.161926 23.875874,110.169411 23.868284,110.175888 23.863453,110.185638 23.863655,110.19516 23.872114,110.199203 23.884029,110.200737 23.893658,110.201767 23.905579,110.206299 23.912907,110.214798 23.911278,110.221024 23.90461,110.2295 23.898849,110.236732 23.894241,110.250504 23.897181,110.257736 23.895323,110.261711 23.888889,110.270638 23.869823,110.275101 23.860407,110.282578 23.856712,110.292839 23.860807,110.296127 23.86974,110.295158 23.877771,110.298698 23.886932,110.302711 23.891048,110.311989 23.898125,110.316559 23.913935,110.315323 23.917837,110.3004 23.936008,110.294434 23.944284,110.290459 23.951406,110.291496 23.962641,110.296799 23.972713,110.301353 23.983936,110.303879 23.991264,110.304649 23.99585,110.30587 23.999998,110.299744 24.007362,110.300446 24.011963,110.301399 24.016104,110.304848 24.021191,110.309814 24.025602,110.317276 24.029812,110.323517 24.031939,110.330986 24.036606,110.337975 24.038971,110.343979 24.039488,110.350494 24.039553,110.355263 24.03845,110.361748 24.041039,110.368973 24.045471,110.373955 24.047586,110.376923 24.051517,110.379707 24.049017,110.383499 24.045382,110.388298 24.041983,110.390839 24.038563)))

注意的问题

  1. indexmapping必须显式声明该字段为geo_shape类型
{
    "ex_index_city_city": {
        "mappings": {
            "ex_type_city_city": {
                "_all": {
                    "enabled": true,
                    "analyzer": "ik_max_word"
                },
                "properties": {
                    "geo_position": {
                        "type": "geo_shape"
                    },
                    "labelId": {
                        "type": "keyword"
                    },
                    "location": {
                        "type": "keyword"
                    },
                    "name": {
                        "type": "keyword"
                    }
                }
            }
        }
    }
}
  1. elasticsearch在高于6.x的版本才对WKT格式的经纬度进行了直接的支持,因此假如你的版本==低于6.x==,在导入数据时需要将WKT格式的转换为GeoJSON.
4.WKT转GeoJson

实体类GeoShapeEntity

public class GeoShapeEntity implements Serializable{

    private static final long serialVersionUID = -4507270609977265606L;
    private String type;
    private Object coordinates;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Object getCoordinates() {
        return coordinates;
    }

    public void setCoordinates(Object coordinates) {
        this.coordinates = coordinates;
    }
}

转换类WKTReaderUtils

private final static Logger logger = LoggerFactory.getLogger(WKTReaderUtils.class);

    private final static WKTReader wktReader = new WKTReader();

    /**
     * 纬度范围
     */
    private final static String[] LAT_BOUNDARY = new String[]{"-90.0","90.0"};
    /**
     * 经度范围
     */
    private final static String[] LON_BOUNDARY = new String[]{"-180.0","180.0"};

    /**
     * 将WKT文本字符串转换为ES中的GeoShape字符串格式
     *
     * @param wkt
     * @return
     */
    public static GeoShapeEntity getESGeoTextFromWkt(String wkt) {
        GeoShapeEntity entity = new GeoShapeEntity();
        try {
            Geometry geom = wktReader.read(wkt);
            if (Objects.isNull(geom)){
                logger.warn("convert wkt to Geometry error!wkt:{}",wkt);
                return null;
            }
            String type = geom.getClass().getSimpleName().toLowerCase();
            Point point;
            MultiPoint multiPoint;
            LineString lineString;
            MultiLineString multiLineString;
            Polygon polygon;
            MultiPolygon multiPolygon;
            Object result = null;
            if (type.equals(GeoShapeEnum.POINT.getEnumFeild())) {
                point = (Point) geom;
                result = getESPointText(point);
            } else if (type.equals(GeoShapeEnum.LINESTRING.getEnumFeild())) {
                lineString = (LineString) geom;
                result = getESLineStringText(lineString);
            } else if (type.equals(GeoShapeEnum.POLYGON.getEnumFeild())) {
                polygon = (Polygon) geom;
                result = getESPolygonText(polygon);
            } else if (type.equals(GeoShapeEnum.MULTIPOINT.getEnumFeild())) {
                multiPoint = (MultiPoint) geom;
                result = getESMultiPointText(multiPoint);
            } else if (type.equals(GeoShapeEnum.MULTILINESTRING.getEnumFeild())) {
                multiLineString = (MultiLineString) geom;
                result = getESMultiLineStringText(multiLineString);
            } else if (type.equals(GeoShapeEnum.MULTIPOLYGON.getEnumFeild())) {
                multiPolygon = (MultiPolygon) geom;
                result = getESMultiPolygonText(multiPolygon);
            }
            entity.setType(type);
            entity.setCoordinates(result);
        } catch (ParseException e) {
            Double[] result = getESPointText(wkt);
            entity.setType("point");
            entity.setCoordinates(result);
        }
        return entity;
    }

    /**
     * 通过MultiPolygon对象拼接中括号表示的字符串
     *
     * @param multiPolygon
     * @return
     */
    private static List getESMultiPolygonText(MultiPolygon multiPolygon) throws ParseException {
        Polygon polygon;
        int num = multiPolygon.getNumGeometries();
        List points = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            polygon = (Polygon) multiPolygon.getGeometryN(i);
            points.add(getESPolygonText(polygon));
        }
        return points;
    }

    /**
     * 通过MultiLineString对象拼接中括号表示的字符串
     *
     * @param multiLineString
     * @return
     */
    private static List> getESMultiLineStringText(MultiLineString multiLineString) {
        LineString lineString;
        int num = multiLineString.getNumGeometries();
        List> points = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            lineString = (LineString) multiLineString.getGeometryN(i);
            points.add(getESLineStringText(lineString));
        }
        return points;
    }

    /**
     * 通过MultiPoint对象拼接中括号表示的字符串
     *
     * @param multiPoint
     * @return
     */
    private static List getESMultiPointText(MultiPoint multiPoint) {
        int num = multiPoint.getNumGeometries();
        List points = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            Point point = (Point) multiPoint.getGeometryN(i);
            points.add(getESPointText(point));
        }
        return points;
    }

    /**
     * 通过Polygon对象拼接中括号表示的字符串
     *
     * @param polygon
     * @return
     * @throws ParseException
     */
    private static List> getESPolygonText(Polygon polygon) {
        /**
         * 内部闭合环形的数量
         */
        int num = polygon.getNumInteriorRing();
        List> points = new ArrayList<>();
        if (num > 0) {
            points.add(getESLineStringText(polygon.getExteriorRing()));
            for (int i = 0; i < num; i++) {
                points.add(getESLineStringText(polygon.getInteriorRingN(i)));
            }
        } else {
            points.add(getESLineStringText(polygon.getExteriorRing()));
        }
        return points;
    }

    /**
     * 通过LineString对象拼接中括号表示的字符串
     *
     * @param lineString
     * @return
     */
    private static List getESLineStringText(LineString lineString) {
        Coordinate[] corrds = lineString.getCoordinates();
        List points = new ArrayList<>();
        for (Coordinate corrd : corrds) {
            points.add(getCoordinateText(corrd));
        }
        return points;
    }

    /**
     * 通过Point对象拼接中括号表示的字符串
     *
     * @param point
     * @return
     */
    private static Double[] getESPointText(Point point) {
        return getCoordinateText(point.getCoordinate());
    }

    /**
     * 通过Coordinate对象拼接中括号表示的字符串
     *
     * @param coord
     * @return
     */
    private static Double[] getCoordinateText(Coordinate coord) {
        Double[] points = new Double[2];
        points[0] = coord.x;
        points[1] = coord.y;
        return points;
    }

    /**
     * 从字符串获取
     *
     * @param value
     * @return
     */
    private static Double[] getESPointText(String value) {
        int comma = value.indexOf(',');
        Double[] points = new Double[2];
        if (comma != -1) {
            double lon = Double.parseDouble(value.substring(0, comma).trim());
            if (lonDouble.valueOf(LON_BOUNDARY[1])){
                logger.error("Error! current lon:[{}] not in boundary [-180,180]!current value:{}", lon,value);
                return null;
            }
            double lat = Double.parseDouble(value.substring(comma + 1).trim());
            if (latDouble.valueOf(LAT_BOUNDARY[1])){
                logger.error("Error! current lat:[{}] not in boundary [-90,90]!current value:{}", lat,value);
                return null;
            }
            points[0] = lon;
            points[1] = lat;
            return points;
        }
        return null;
    }

    /**
     * 将经纬度转换为数组
     * @param latObj 纬度
     * @param lonObj 经度
     * @return
     */
    public static Double[] getESPointText(Object latObj, Object lonObj) {
        Double[] points = new Double[2];
        if (Objects.isNull(latObj)||Objects.isNull(lonObj)){
            return null;
        }
        double lat = Double.parseDouble(latObj.toString());
        if (latDouble.valueOf(LAT_BOUNDARY[1])){
            logger.error("Error! current lat:[{}] not in boundary [-90,90]!", lat);
            return null;
        }
        double lon = Double.parseDouble(lonObj.toString());
        if (lonDouble.valueOf(LON_BOUNDARY[1])){
            logger.error("Error! current lon:[{}] not in boundary [-180,180]!", lon);
            return null;
        }
        points[0] = lon;
        points[1] = lat;
        return points;
    }

    /**
     * 将数组格式的经纬度转换为wkt格式
     * @param points
     * @return
     */
    public static String transformWKt(Double[] points){
        StringBuilder wktBuilder = new StringBuilder();
        wktBuilder.append("POINT");
        wktBuilder.append("(");
        wktBuilder.append(transform(points));
        wktBuilder.append(")");
        return wktBuilder.toString();
    }

    /**
     * 将list格式的经纬度转换为wkt格式
     * @param points
     * @return
     */
    public static String transformWKT(List points){
        StringBuilder wktBuilder = new StringBuilder();
        wktBuilder.append("POINT");
        wktBuilder.append("(");
        int num = 0;
        for (Double[] point : points){
            wktBuilder.append(transform(point));
            num++;
            if (num!=points.size()){
                wktBuilder.append(",");
            }
        }
        wktBuilder.append(")");
        return wktBuilder.toString();
    }

    public static String transform(Double[] points){
        return points[0]+" "+points[1];
    }

这样我们可以将WKT形式的坐标信息导入我们的ES中。

5. 如何查询
  1. 构建wkt查询条件
/**
     * 构建Wkt条件
     *
     * @date 2019/9/26
     */
    private BoolQueryBuilder buildWktBoolQueryBuilder(String queryField, List wkts) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        WKTReader wktReader = new WKTReader();
        try {
            for (String wkt : wkts) {
                Geometry geom = wktReader.read(wkt);
                String type = geom.getClass().getSimpleName().toLowerCase();
                GeoShapeQueryBuilder geoShapeQueryBuilder = null;
                if (type.equals(GeoShapeEnum.POINT.getEnumFeild())) {
                    Point point = (Point) geom;
                    PointBuilder pointBuilder = ShapeBuilders.newPoint(point.getCoordinate());
                    geoShapeQueryBuilder = QueryBuilders
                            .geoShapeQuery(queryField, pointBuilder)
                            .relation(ShapeRelation.CONTAINS);
                    boolQueryBuilder.should(geoShapeQueryBuilder);
                } else if (type.equals(GeoShapeEnum.LINESTRING.getEnumFeild())) {
                    LineString lineString = (LineString) geom;
                    List coordinates = Arrays.stream(lineString.getCoordinates()).collect(Collectors.toList());
                    LineStringBuilder lineStringBuilder = ShapeBuilders.newLineString(coordinates);
                    geoShapeQueryBuilder = QueryBuilders
                            .geoShapeQuery(queryField, lineStringBuilder)
                            .relation(ShapeRelation.INTERSECTS);
                    boolQueryBuilder.should(geoShapeQueryBuilder);
                } else if (type.equals(GeoShapeEnum.POLYGON.getEnumFeild())) {
                    Polygon polygon = (Polygon) geom;
                    List coordinates = Arrays.stream(polygon.getCoordinates()).collect(Collectors.toList());
                    PolygonBuilder polygonBuilder = ShapeBuilders.newPolygon(coordinates);
                    geoShapeQueryBuilder = QueryBuilders
                            .geoShapeQuery(queryField, polygonBuilder)
                            .relation(ShapeRelation.WITHIN);
                    boolQueryBuilder.should(geoShapeQueryBuilder);
                } else if (type.equals(GeoShapeEnum.MULTIPOINT.getEnumFeild())) {
                    MultiPoint multiPoint = (MultiPoint) geom;
                    int num = multiPoint.getNumGeometries();
                    List coordinates = new ArrayList<>();
                    for (int i = 0; i < num; i++) {
                        Point point = (Point) multiPoint.getGeometryN(i);
                        coordinates.add(point.getCoordinate());
                    }
                    MultiPointBuilder multiPointBuilder = ShapeBuilders.newMultiPoint(coordinates);
                    geoShapeQueryBuilder = QueryBuilders
                            .geoShapeQuery(queryField, multiPointBuilder)
                            .relation(ShapeRelation.INTERSECTS);
                    boolQueryBuilder.should(geoShapeQueryBuilder);
                } else if (type.equals(GeoShapeEnum.MULTILINESTRING.getEnumFeild())) {
                    MultiLineString multiLineString = (MultiLineString) geom;
                    int num = multiLineString.getNumGeometries();
                    MultiLineStringBuilder multiLineStringBuilder = ShapeBuilders.newMultiLinestring();
                    for (int i = 0; i < num; i++) {
                        LineString lineString = (LineString) multiLineString.getGeometryN(i);
                        List coordinates = Arrays.stream(lineString.getCoordinates()).collect(Collectors.toList());
                        multiLineStringBuilder.linestring(ShapeBuilders.newLineString(coordinates));
                    }
                } else if (type.equals(GeoShapeEnum.MULTIPOLYGON.getEnumFeild())) {
                    MultiPolygon multiPolygon = (MultiPolygon) geom;
                    int num = multiPolygon.getNumGeometries();
                    MultiPolygonBuilder multiPolygonBuilder = ShapeBuilders.newMultiPolygon();
                    for (int i = 0; i < num; i++) {
                        Polygon polygon = (Polygon) multiPolygon.getGeometryN(i);
                        List coordinates = Arrays.stream(polygon.getCoordinates()).collect(Collectors.toList());
                        multiPolygonBuilder.polygon(ShapeBuilders.newPolygon(coordinates));
                    }
                    geoShapeQueryBuilder = QueryBuilders
                            .geoShapeQuery(queryField, multiPolygonBuilder)
                            .relation(ShapeRelation.WITHIN);
                    boolQueryBuilder.should(geoShapeQueryBuilder);
                }
            }
        } catch (Exception e) {
            LOGGER.error("构建Wkt条件错误", e);
        }
        return boolQueryBuilder;
    }
  1. 查询方法
/**
     * 传入形状,查询数据
     *
     * @param indices 索引
     * @param queryField 查询字段,必须是geo_shape类型
     * @param wkt
     * @param include    限定返回字段
     * @return
     */
public List> queryDataWithGivingShape(List indices, String queryField, List include, List wkts) {
        try {
            BoolQueryBuilder boolQueryBuilder = buildWktBoolQueryBuilder(queryField, wkts);
            return handleResult(indices, queryField, include, boolQueryBuilder);
        } catch (Exception e) {
            LOGGER.error("query shape error!index:{},queryField:{}", indices, queryField, e);
        }
        return null;
    }
  1. 测试类
 @Test
    public void testGeoPolygon() throws Exception {
//        String wkt = "POLYGON((108.36819648742677 22.795133732106507," +
//                "108.37102890014648 22.7784369185635," +
//                "108.38510513305664 22.777882960812377," +
//                "108.40819358825684 22.780019642602568," +
//                "108.41154098510742 22.79291815884342," +
//                "108.39059829711913 22.80035601233493," +
//                "108.36819648742677 22.795133732106507))";

//        String wkt = "POLYGON((108.36549282073975 22.797566864832092,108.35974216461182 22.786093175673713,108.37265968322754 22.775963875498206,108.4035587310791 22.77600344454008,108.41003894805907 22.787557113881462,108.39557647705077 22.805360509802284,108.36549282073975 22.797566864832092))";
        String wkt = "POLYGON((110.20111083984375 25.431803168948832,110.05897521972658 25.32075284544021,110.07476806640624 25.187233664941914,110.643310546875 25.1070518051296,110.62477111816405 25.230721136478365,110.55198669433594 25.446064798199416,110.35491943359375 25.353644304321108,110.21072387695312 25.299647958643703,110.17501831054689 25.312683764022793,110.20111083984375 25.431803168948832))";
        long currentTimeMillis = System.currentTimeMillis();
        List> maps = esDataQueryDao.
                queryDataWithGivingShape(Arrays.asList("ex_index_city_city"), "geo_position",null, Collections.singletonList(wkt));
        System.out.println(maps);
    }

你可能感兴趣的:(ES地理范围查询第二讲:地理位置信息之geo_shape)