{"id":9628,"date":"2020-11-04T15:51:31","date_gmt":"2020-11-04T23:51:31","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=9628"},"modified":"2024-03-01T09:18:35","modified_gmt":"2024-03-01T17:18:35","slug":"taming-the-gerrymander-with-geospatial-search","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/es\/taming-the-gerrymander-with-geospatial-search\/","title":{"rendered":"Domar el gerrymander con la b\u00fasqueda geoespacial"},"content":{"rendered":"<h4>Conceptos b\u00e1sicos<\/h4>\n<p>Antes de seguir leyendo, t\u00f3mese unos minutos y lea el excelente post sobre <a href=\"https:\/\/www.couchbase.com\/blog\/es\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/\">b\u00fasqueda geoespacial<\/a> en Couchbase, publicado por mi amigo y colega Brian Kane: <a href=\"https:\/\/www.couchbase.com\/blog\/es\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/<\/a><\/p>\n<p>Adelante; esperar\u00e9.<\/p>\n<p>Ahora que has vuelto, sabr\u00e1s que una forma estupenda de aprovechar el motor de b\u00fasqueda de texto completo de Couchbase es pasarle una serie de v\u00e9rtices que identifiquen un pol\u00edgono (normalmente irregular) que describa una regi\u00f3n geogr\u00e1fica. El ejemplo de Brian utiliza diez pares de puntos lat\/long:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">\"polygon_points\": [\r\n  \"35.987374, -83.658937\",\r\n  \"35.971769, -83.654212\",\r\n  \"35.887168, -83.793874\",\r\n  \"35.686403, -83.678068\",\r\n  \"35.704374, -83.505435\",\r\n  \"35.769145, -83.275637\",\r\n  \"35.868423, -83.290819\",\r\n  \"35.919168, -83.350486\",\r\n  \"35.948053, -83.510420\",\r\n  \"35.990925, -83.568382\"\r\n]<\/pre>\n<p>Estos puntos delimitan aproximadamente una regi\u00f3n de Tennessee, al sur de la autopista, al norte del l\u00edmite del Parque Nacional y dentro de un \u00fanico condado... suficientemente bueno para el an\u00e1lisis requerido, y f\u00e1cil de pegar en tu solicitud. Teniendo esto en cuenta, el motor de \u00edndice de b\u00fasqueda de texto completo (FTS) de Couchbase puede devolver f\u00e1cilmente todos los elementos de datos necesarios asociados con puntos dentro (o fuera) del per\u00edmetro. (Brian da un gran ejemplo de esto en su post).<\/p>\n<h4>La llave inglesa (o quiz\u00e1, el distrito con forma de llave inglesa)<\/h4>\n<p>Pero, \u00bfy si su regi\u00f3n poligonal es extremadamente detallada y compleja, y requiere tal vez miles de pares de puntos lat\/long para describirla? \u00bfDisponemos de ejemplos de este tipo? S\u00ed. Gracias a la ardua labor de las legislaturas de los cincuenta estados y\/o sus sustitutos, tenemos muchos ejemplos de regiones de este tipo en forma de distritos del Congreso de los Estados Unidos. Y gracias a Couchbase N1QL y a la b\u00fasqueda geoespacial FTS, tenemos los medios para gestionar los datos con facilidad.<\/p>\n<p>El distrito medio del Congreso de EE.UU. requiere 8.694 v\u00e9rtices para definirse. Esto se debe a razones pr\u00e1cticas (se espera que todos los distritos tengan aproximadamente el mismo n\u00famero de ciudadanos), pol\u00edticas (los partidos en el poder pueden deformar los l\u00edmites de los distritos para que los votantes los mantengan as\u00ed, lo que se denomina \"gerrymandering\") y geogr\u00e1ficas (muchos de ellos se basan en parte en r\u00edos, lagos, costas oce\u00e1nicas, monta\u00f1as y otros l\u00edmites naturales). El distrito geogr\u00e1ficamente m\u00e1s complejo (es decir, el que requiere el mayor n\u00famero de v\u00e9rtices para ser descrito) es el 5\u00ba distrito electoral de Virginia, que necesita la friolera de 40.145 pares de latitud y longitud para ser descrito (y parece un T. Rex rampante al rev\u00e9s). El m\u00e1s sencillo, que s\u00f3lo requiere 422, es el 36\u00ba Distrito Electoral de Nueva York, que parece un submarino escabull\u00e9ndose del lago Erie.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-9629 size-full\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/11\/StateDistricts.png\" alt=\"\" width=\"1352\" height=\"340\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/StateDistricts.png 1352w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/StateDistricts-300x75.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/StateDistricts-1024x258.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/StateDistricts-768x193.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/StateDistricts-20x5.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/StateDistricts-1320x332.png 1320w\" sizes=\"auto, (max-width: 1352px) 100vw, 1352px\" \/><\/p>\n<h4>Los datos<\/h4>\n<p>Claramente, entonces, vamos a querer almacenar y recuperar nuestros puntos geogr\u00e1ficos de una base de datos si queremos implementar consultas contra ellos a gran escala. Y debido a que los puntos se encuentran probablemente en forma de una matriz incrustada, un documento JSON en Couchbase es justo el billete. Abajo hay un ejemplo de tal documento:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">{\r\n\"geometry\": {\r\n\"type\": \"Polygon\",\r\n\"coordinates\": [\r\n{\r\n  \"geometry\": {\r\n    \"type\": \"Polygon\",\r\n    \"coordinates\": [\r\n      [\r\n        [-93.911307,44.546513999999995],\r\n        [-93.91024,44.548004999999996],\r\n        [-93.909904,44.548300999999995],\r\n        [-93.90922599999999,44.548843999999995],\r\n        [etc., etc., for hundreds or thousands of pairs]\r\n        [-93.911307,44.546513999999995]\r\n      ]\r\n    ]\r\n  },\r\n\"type\": \"Feature\",\r\n\"properties\": {\r\n\"INTPTLAT\": \"+44.4789680\",\r\n\"FUNCSTAT\": \"N\",\r\n\"INTPTLON\": \"-092.8530418\",\r\n\"LSAD\": \"C2\",\r\n\"GEOID\": \"2702\",\r\n\"AWATER\": 243358361,\r\n\"CD116FP\": \"02\",\r\n\"CDSESSN\": \"116\",\r\n\"MTFCC\": \"G5200\",\r\n\"NAMELSAD\": \"Congressional District 2\",\r\n\"STATEFP\": \"27\",\r\n\"ALAND\": 6314464923\r\n}\r\n}\r\n\r\n<\/pre>\n<p>\u00bfPor qu\u00e9 los datos tienen esta forma, te preguntar\u00e1s, con los puntos del pol\u00edgono incrustados en un array de un solo elemento sin nombre, incrustado en otro de \"coordenadas\", incrustado en un objeto de \"geometr\u00eda\"? La respuesta sencilla es que a veces simplemente se trabaja con los datos que se tienen. (Se basa en la fuente p\u00fablica que pude encontrar, una que era notablemente f\u00e1cil de importar a Couchbase. Tal vez escriba un post aparte describiendo ese proceso). Y aunque los datos son un poco engorrosos, el lenguaje N1QL, como veremos m\u00e1s adelante, facilita la recuperaci\u00f3n de lo que necesitamos.<\/p>\n<p>El otro conjunto de datos que nos ocupa constituye la parte principal de nuestro ejemplo. Se trata de una lista de millones de votantes registrados (no te preocupes, he falsificado los nombres y las direcciones), junto con la afiliaci\u00f3n a un partido y el historial de voto de cada uno. Un documento de muestra tiene este aspecto:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">{\r\n  \"City\": \"Adelanto\",\r\n  \"doctype\": \"Voter\",\r\n  \"Name\": \"Ryan Johnson\",\r\n  \"County\": \"San Bernardino\",\r\n  \"Party\": \"Democrat\",\r\n  \"Reg\": [{\"Year\": 2018},\r\n          {\"Voted\": \"In person\",\"Year\": 2016},\r\n          {\"Year\": 2014},\r\n          {\"Voted\": \"In person\",\"Year\": 2012},\r\n          {\"Year\": 2010},\r\n          {\"Voted\": \"In person\",\"Year\": 2008},\r\n          {\"Year\": 2006},\r\n          {\"Voted\": \"In person\",\"Year\": 2004},\r\n          {\"Year\": 2002},\r\n          {\"Voted\": \"In person\",\"Year\": 2000},\r\n          {\"Year\": 1998},\r\n          {\"Voted\": \"In person\",\"Year\": 1996}],\r\n  \"Addr\": \"221 Cindy Inlet Suite 064\",\r\n  \"Zip\": \"92301\",\r\n  \"Geo\": {\"lat\": 34.6149071942612,\"lon\": -117.51442556265236}\r\n}<\/pre>\n<h4>Caso pr\u00e1ctico y configuraci\u00f3n<\/h4>\n<p>Por \u00faltimo, nuestro caso pr\u00e1ctico: Dado un elector individual por tel\u00e9fono, \u00bfc\u00f3mo puede un miembro del Congreso determinar r\u00e1pidamente si la persona es o no miembro de su distrito electoral? Resolveremos el problema con FTS y N1QL.<\/p>\n<p>Primero debemos preparar el \u00edndice FTS. En nuestro caso, indexaremos todos los documentos en funci\u00f3n del campo de tipo <em>Tipo<\/em>. Indexaremos el <em>Nombre<\/em> como palabra clave, y el campo <em>Geo<\/em> como geopunto. Esto es lo que se ve en mi consola:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-9631 size-large\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/11\/Screen-Shot-2020-11-03-at-2.27.01-PM-1024x490.png\" alt=\"\" width=\"900\" height=\"431\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Screen-Shot-2020-11-03-at-2.27.01-PM-1024x490.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Screen-Shot-2020-11-03-at-2.27.01-PM-300x144.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Screen-Shot-2020-11-03-at-2.27.01-PM-768x368.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Screen-Shot-2020-11-03-at-2.27.01-PM-1536x736.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Screen-Shot-2020-11-03-at-2.27.01-PM-20x10.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Screen-Shot-2020-11-03-at-2.27.01-PM-1320x632.png 1320w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Screen-Shot-2020-11-03-at-2.27.01-PM.png 1758w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<p>(El post de Brian profundiza en los pasos a seguir para construir un \u00edndice).<\/p>\n<p>Una vez construido este \u00edndice, podremos pasarle una serie de puntos poligonales y recibir una serie de aciertos. Siguiendo el ejemplo de Brian, he probado esto usando un curl:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">curl -s -XPOST -H \"Content-Type: application\/json\" -u Administrator:password https:\/\/localhost:8094\/api\/index\/ftsVoterGeo\/query -d '\r\n{\r\n  \"fields\": [\"Name\"],\r\n  \"size\": 50,\r\n  \"query\": {\r\n    \"field\": \"Geo\",\r\n    \"polygon_points\": [\r\n      \"33.4328, -114.7322\",\r\n      \"33.5253, -114.6561\",\r\n      \"33.6178, -114.5883\",\r\n      \"34.6173, -117.4220\"\r\n    ]\r\n  }\r\n}' | jq '(\"result_count: \"+ (.total_hits | tostring)), (.hits[]| (.id + \" \" + .fields.Name))'<\/pre>\n<p>Esto me demuestra que una b\u00fasqueda en una simple regi\u00f3n poligonal puede devolver y devolver\u00e1 una lista de nombres. En teor\u00eda, podr\u00edamos detenernos ah\u00ed y dejar que la aplicaci\u00f3n (o incluso el usuario) buscara entre los resultados para ver si encuentra el nombre del votante en cuesti\u00f3n. Pero podemos hacerlo mejor. Dejemos que el motor de b\u00fasqueda acote la b\u00fasqueda. Lo haremos mediante una b\u00fasqueda \"conjunta\". (Piense en un conjunto como un AND l\u00f3gico y un disyunto como un OR l\u00f3gico). A continuaci\u00f3n se muestra el ejemplo de curl:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">curl -s -XPOST -H \"Content-Type: application\/json\" -u Administrator:password https:\/\/localhost:8094\/api\/index\/ftsVoterGeo\/query -d '\r\n{\r\n  \"fields\": [\"Name\"],\r\n  \"size\": 50,\r\n  \"query\":\r\n  {\r\n    \"conjuncts\":\r\n      [\r\n        {\r\n        \"field\": \"Geo\",\r\n        \"polygon_points\": [\r\n           \"33.4328, -114.7322\",\r\n           \"33.5253, -114.6561\",\r\n           \"33.6178, -114.5883\",\r\n           \"34.6173, -117.4220\"\r\n        ]\r\n        },\r\n        {\r\n        \"field\": \"Name\",\r\n        \"match\": \"Anne Murray\"\r\n        }\r\n      ]\r\n  }\r\n}' | jq '(\"result_count: \"+ (.total_hits | tostring)), (.hits[]| (.id + \" \" + .fields.Name))'<\/pre>\n<p>Puedes leer esto como \"Si el geopunto est\u00e1 dentro de los l\u00edmites del pol\u00edgono y el nombre coincide con el nombre del votante, devuelve el acierto\". Funciona a las mil maravillas, as\u00ed que sabemos que nuestro \u00edndice FTS est\u00e1 correctamente definido.<\/p>\n<h4>La extracci\u00f3n<\/h4>\n<p>Ahora tenemos que probar la recuperaci\u00f3n de los l\u00edmites de un distrito individual de la base de datos. El primer paso consiste en una simple inspecci\u00f3n de los datos que vamos a utilizar, quiz\u00e1 de un solo distrito:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">select properties.NAMELSAD, districts.geometry.coordinates from districts\r\n      use keys 'district::87';<\/pre>\n<p>Esto devuelve un resultado como este:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">[\r\n    {\r\n        \"NAMELSAD\": \"Congressional District 8\",\r\n        \"coordinates\": [\r\n            [\r\n                [\r\n                    -119.651375,\r\n                    38.286637999999996\r\n                ],\r\n                [\r\n                    -119.650185,\r\n                    38.287234\r\n                ],<\/pre>\n<p>...y as\u00ed sucesivamente durante otros 1,3 MB de un conjunto de resultados. No es de extra\u00f1ar que no queramos cortar y pegar esto.<\/p>\n<p>Nuestro objetivo, recuerda, es acabar con algo parecido a esto:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">[\r\n   \"33.4328, -114.7322\",\r\n   \"33.5253, -114.6561\",\r\n   \"33.6178, -114.5883\",\r\n   \"34.6173, -117.4220\"\r\n]<\/pre>\n<p>As\u00ed es como acabamos:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">select value concat(tostring(c[1]),\", \",tostring(c[0])) points\r\nfrom (\r\n      select value districts.geometry.coordinates[0] from districts\r\n      use keys 'district::87'\r\n      )[0] c;<\/pre>\n<p>Esto es un trabalenguas, as\u00ed que vamos a desentra\u00f1arlo. Recuerde que estamos trabajando con los datos que tenemos, en lugar de lo que idealmente podr\u00edamos querer, y los puntos del pol\u00edgono que estamos buscando est\u00e1n incrustados en una matriz de un solo elemento sin nombre, incrustado en otro de \"coordenadas\", incrustado en un objeto de \"geometr\u00eda\". Tenemos que desenrollarlos uno a uno. En primer lugar, vamos a eliminar la envoltura de la matriz sin nombre. Para ello, basta con solicitar que s\u00f3lo se devuelva el \u00fanico (primer o \"zeroth\") miembro de la matriz:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">select districts.geometry.coordinates[0] from districts\r\n      use keys 'district::87'<\/pre>\n<p>El objeto JSON devuelto por esta consulta tiene el siguiente aspecto:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">[\r\n    {\r\n        \"$1\": [\r\n            [\r\n                -119.651375,\r\n                38.286637999999996\r\n            ],\r\n            [\r\n                -119.650185,\r\n                38.287234\r\n            ],\r\n            [\r\n                -119.650139,\r\n                38.287678\r\n            ],<\/pre>\n<p>Podemos convertirlo en un array (en lugar de un objeto JSON) utilizando select value:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">select value districts.geometry.coordinates[0] from districts\r\n      use keys 'district::87'<\/pre>\n<p>Ahora tenemos el array muy grande que buscamos, a\u00fan envuelto en el \u00fanico elemento de otro array:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">[\r\n    [\r\n        [\r\n            -119.651375,\r\n            38.286637999999996\r\n        ],\r\n        [\r\n            -119.650185,\r\n            38.287234\r\n        ],\r\n        [\r\n            -119.650139,\r\n            38.287678\r\n        ],\r\n        [\r\n            -119.650154,\r\n            38.288041<\/pre>\n<p>Seleccionemos de ese conjunto de devoluciones:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">select * from (\r\nselect value districts.geometry.coordinates[0] from districts\r\nuse keys 'district::87')[0] c<\/pre>\n<p>Esto da lugar a un mont\u00f3n de peque\u00f1os objetos que podemos plegar a nuestra voluntad:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">[\r\n    {\r\n        \"c\": [\r\n            -119.651375,\r\n            38.286637999999996\r\n        ]\r\n    },\r\n    {\r\n        \"c\": [\r\n            -119.650185,\r\n            38.287234\r\n        ]\r\n    },<\/pre>\n<p>Ahora que podemos abordarlos vamos a convertir los tipos y realizar nuestra concatenaci\u00f3n:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">select concat(tostring(c[1]),\", \",tostring(c[0])) points from (\r\nselect value districts.geometry.coordinates[0] from districts\r\n      use keys 'district::87')[0] c<\/pre>\n<p>Los objetos resultantes tienen este aspecto:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">[\r\n  {\r\n    \"points\": \"38.286637999999996, -119.651375\"\r\n  },\r\n  {\r\n    \"points\": \"38.287234, -119.650185\"\r\n  },\r\n  {\r\n    \"points\": \"38.287678, -119.650139\"\r\n  },<\/pre>\n<p>Ahora usa select value para recibirlos como un array:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">select value concat(tostring(c[1]),\", \",tostring(c[0])) points from (\r\nselect value districts.geometry.coordinates[0] from districts\r\n      use keys 'district::87')[0] c<\/pre>\n<p>Y tenemos los resultados que busc\u00e1bamos:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">[\r\n  \"38.286637999999996, -119.651375\",\r\n  \"38.287234, -119.650185\",\r\n  \"38.287678, -119.650139\",\r\n  \"38.288041, -119.650154\",\r\n  \"38.288593999999996, -119.649699\",<\/pre>\n<h4>La facilidad de los CTE<\/h4>\n<p>El \u00faltimo truco que nos queda es un buen truco. Necesitamos una forma de referenciar el array que contiene los geopuntos como componente de una sentencia SQL m\u00e1s amplia. Afortunadamente, N1QL nos proporciona los medios para hacerlo en forma de Expresiones de Tabla Comunes (CTE).  Las CTE, que se a\u00f1aden a una consulta mediante la funci\u00f3n <em>con<\/em> se eval\u00faan una vez por bloque de consulta y pueden introducirse antes de una selecci\u00f3n. Esto es exactamente lo que buscamos:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">with geopoints as\r\n(\r\nselect value concat(tostring(c[1]),\", \",tostring(c[0])) points\r\nfrom ((select value d.geometry.coordinates[0] from districts d use keys 'district::87')[0]) c\r\n)<\/pre>\n<p>Ahora tenemos acceso a un conjunto de retorno evaluado \"geopuntos\" al que se puede hacer referencia en posteriores (o m\u00faltiples posteriores) sentencias SQL. Perfecto. Aqu\u00ed se utiliza en la consulta final:<\/p>\n<pre class=\"toolbar-overlay:false toolbar-hide:false toolbar-delay:false show-title:false striped:false marking:false ranges:false nums:false nums-toggle:false wrap-toggle:false expand-toggle:false decode-attributes:false trim-whitespace:false trim-code-tag:false mixed:false show_mixed:false lang:default decode:true show_mixed:false\">with geopoints as\r\n(\r\nselect value concat(tostring(c[1]),\", \",tostring(c[0])) points\r\nfrom ((select value d.geometry.coordinates[0] from districts d use keys 'district::87')[0]) c\r\n)\r\n\r\nselect Name\r\nfrom voters AS v\r\nwhere v._type = \"Voter\" AND search(v.Geo,\r\n{\r\n  \"query\":\r\n  {\r\n    \"conjuncts\":\r\n      [\r\n        {\r\n        \"field\": \"Geo\",\r\n        \"polygon_points\": geopoints\r\n        },\r\n        {\r\n        \"field\": \"Name\",\r\n        \"match\": \"Anne Murray\"\r\n        }\r\n      ]\r\n  }\r\n}\r\n);<\/pre>\n<p>Aqu\u00ed est\u00e1:  Un sencillo bloque de c\u00f3digo de una sola pantalla que recupera los l\u00edmites complejos de un distrito y los aprovecha como parte de una b\u00fasqueda geoespacial impulsada por N1QL.  Pruebe esta t\u00e9cnica y supere sus propios retos geogr\u00e1ficos.<\/p>\n<p><em>Muchas gracias a Brian Kane por su post original y a Dmitry Lychagin por su ayuda para desentra\u00f1ar las matrices anidadas.<\/em><\/p>","protected":false},"excerpt":{"rendered":"<p>The Basics Before you read any further, please take a few minutes and read the excellent post on geospatial search in Couchbase, as published by my friend and colleague Brian Kane: https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/ Go ahead; I&#8217;ll wait. Now that you&#8217;re back, [&hellip;]<\/p>","protected":false},"author":41576,"featured_media":9633,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[2165,8683,1812],"tags":[],"ppma_author":[9066],"class_list":["post-9628","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-full-text-search","category-geospatial","category-n1ql-query"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.7.1 (Yoast SEO v25.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Taming the Gerrymander with Geospatial Search - The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"Combining Couchbase geospatial search with N1QL queries will allow you to conquer complex geographical boundaries.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/es\/taming-the-gerrymander-with-geospatial-search\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Taming the Gerrymander with Geospatial Search\" \/>\n<meta property=\"og:description\" content=\"Combining Couchbase geospatial search with N1QL queries will allow you to conquer complex geographical boundaries.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/es\/taming-the-gerrymander-with-geospatial-search\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2020-11-04T23:51:31+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-03-01T17:18:35+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/11\/Taming-the-Gerrymander-with-Geospatial-Search.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"627\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Peter Reale\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Peter Reale\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/\"},\"author\":{\"name\":\"Peter Reale\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/391cf559b28ca6b4c1660a1ce283752c\"},\"headline\":\"Taming the Gerrymander with Geospatial Search\",\"datePublished\":\"2020-11-04T23:51:31+00:00\",\"dateModified\":\"2024-03-01T17:18:35+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/\"},\"wordCount\":1342,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Gerrymander.jpg\",\"articleSection\":[\"Full-Text Search\",\"Geospatial\",\"SQL++ \/ N1QL Query\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/\",\"name\":\"Taming the Gerrymander with Geospatial Search - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Gerrymander.jpg\",\"datePublished\":\"2020-11-04T23:51:31+00:00\",\"dateModified\":\"2024-03-01T17:18:35+00:00\",\"description\":\"Combining Couchbase geospatial search with N1QL queries will allow you to conquer complex geographical boundaries.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Gerrymander.jpg\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Gerrymander.jpg\",\"width\":1764,\"height\":1847},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Taming the Gerrymander with Geospatial Search\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/391cf559b28ca6b4c1660a1ce283752c\",\"name\":\"Peter Reale\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/ec988e11a3058e02331c83244e993ea2\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/19012c1e7433fcde0d634a14a0f76610c40ce876b6c5a04b23d43c2181301761?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/19012c1e7433fcde0d634a14a0f76610c40ce876b6c5a04b23d43c2181301761?s=96&d=mm&r=g\",\"caption\":\"Peter Reale\"},\"description\":\"Peter Reale is a Senior Solutions Engineer at Couchbase and has been in the data business since 1984. He is based in Los Angeles.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/es\/author\/peter-reale\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Taming the Gerrymander with Geospatial Search - The Couchbase Blog","description":"Combining Couchbase geospatial search with N1QL queries will allow you to conquer complex geographical boundaries.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/es\/taming-the-gerrymander-with-geospatial-search\/","og_locale":"es_MX","og_type":"article","og_title":"Taming the Gerrymander with Geospatial Search","og_description":"Combining Couchbase geospatial search with N1QL queries will allow you to conquer complex geographical boundaries.","og_url":"https:\/\/www.couchbase.com\/blog\/es\/taming-the-gerrymander-with-geospatial-search\/","og_site_name":"The Couchbase Blog","article_published_time":"2020-11-04T23:51:31+00:00","article_modified_time":"2024-03-01T17:18:35+00:00","og_image":[{"width":1200,"height":627,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/11\/Taming-the-Gerrymander-with-Geospatial-Search.png","type":"image\/png"}],"author":"Peter Reale","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Peter Reale","Est. reading time":"7 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/"},"author":{"name":"Peter Reale","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/391cf559b28ca6b4c1660a1ce283752c"},"headline":"Taming the Gerrymander with Geospatial Search","datePublished":"2020-11-04T23:51:31+00:00","dateModified":"2024-03-01T17:18:35+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/"},"wordCount":1342,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Gerrymander.jpg","articleSection":["Full-Text Search","Geospatial","SQL++ \/ N1QL Query"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/","url":"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/","name":"Taming the Gerrymander with Geospatial Search - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Gerrymander.jpg","datePublished":"2020-11-04T23:51:31+00:00","dateModified":"2024-03-01T17:18:35+00:00","description":"Combining Couchbase geospatial search with N1QL queries will allow you to conquer complex geographical boundaries.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Gerrymander.jpg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/11\/Gerrymander.jpg","width":1764,"height":1847},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/taming-the-gerrymander-with-geospatial-search\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Taming the Gerrymander with Geospatial Search"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"El blog de Couchbase","description":"Couchbase, la base de datos NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"El blog de Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/391cf559b28ca6b4c1660a1ce283752c","name":"Peter Reale","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/ec988e11a3058e02331c83244e993ea2","url":"https:\/\/secure.gravatar.com\/avatar\/19012c1e7433fcde0d634a14a0f76610c40ce876b6c5a04b23d43c2181301761?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/19012c1e7433fcde0d634a14a0f76610c40ce876b6c5a04b23d43c2181301761?s=96&d=mm&r=g","caption":"Peter Reale"},"description":"Peter Reale is a Senior Solutions Engineer at Couchbase and has been in the data business since 1984. He is based in Los Angeles.","url":"https:\/\/www.couchbase.com\/blog\/es\/author\/peter-reale\/"}]}},"authors":[{"term_id":9066,"user_id":41576,"is_guest":0,"slug":"peter-reale","display_name":"Peter Reale","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/19012c1e7433fcde0d634a14a0f76610c40ce876b6c5a04b23d43c2181301761?s=96&d=mm&r=g","first_name":"Peter","last_name":"Reale, Senior Solutions Engineer, Couchbase","user_url":"","author_category":"","description":"Peter Reale es Ingeniero Senior de Soluciones en Couchbase y lleva en el negocio de los datos desde 1984.  Reside en Los \u00c1ngeles."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/9628","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/users\/41576"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/comments?post=9628"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/9628\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media\/9633"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media?parent=9628"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/categories?post=9628"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/tags?post=9628"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/ppma_author?post=9628"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}