{"id":13092,"date":"2022-04-20T10:22:45","date_gmt":"2022-04-20T17:22:45","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=13092"},"modified":"2025-06-13T23:34:37","modified_gmt":"2025-06-14T06:34:37","slug":"creating-python-and-javascript-user-defined-functions-for-geospatial-queries","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/es\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/","title":{"rendered":"Creaci\u00f3n de funciones definidas por el usuario en Python y JavaScript para consultas geoespaciales"},"content":{"rendered":"<p><span style=\"font-weight: 400\">Las consultas SQL++ pueden acceder a los datos almacenados en tu cluster Couchbase de varias maneras. Hay situaciones en las que tener la l\u00f3gica de negocio como parte de tus consultas de datos tambi\u00e9n puede ser beneficioso. SQL++ soporta esto con Funciones Definidas por el Usuario (UDFs) que han estado disponibles desde <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/es\/n1ql-user-defined-functions\/\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">Couchbase 7.0<\/span><\/a><span style=\"font-weight: 400\">.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">En esta entrada de blog, creamos una UDF en JavaScript que consulta puntos a partir de la ubicaci\u00f3n de un usuario, de forma din\u00e1mica, utilizando SQL++. Adem\u00e1s, realizamos los mismos c\u00e1lculos de distancia con una UDF en Python dentro de la aplicaci\u00f3n <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/analytics\/introduction.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">Servicio de an\u00e1lisis<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<h2><span style=\"font-weight: 400\">Nuestro caso de consulta geoespacial<\/span><\/h2>\n<p><span style=\"font-weight: 400\">Nuestra aplicaci\u00f3n generar\u00e1 puntos geogr\u00e1ficos de inter\u00e9s a partir de nuestra base de datos que est\u00e9n cerca de la ubicaci\u00f3n GPS de un usuario, de forma similar a servicios como Google Maps, que se muestra en la captura de pantalla siguiente. Para este ejemplo, utilizaremos la funci\u00f3n <\/span><a href=\"https:\/\/docs.couchbase.com\/java-sdk\/current\/ref\/travel-app-data-model.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">conjunto de datos de muestras de viajes<\/span><\/a><span style=\"font-weight: 400\"> que est\u00e1 disponible en un bucket de ejemplo proporcionado por Couchbase.<\/span><\/p>\n<p><span style=\"font-weight: 400\">En particular, nos interesa ver la <\/span><i><span style=\"font-weight: 400\">hitos <\/span><\/i><span style=\"font-weight: 400\">y <\/span><i><span style=\"font-weight: 400\">aeropuertos <\/span><\/i><span style=\"font-weight: 400\">alrededor de la ubicaci\u00f3n actual del usuario. Esto no puede conseguirse utilizando directamente una consulta SQL++, ya que el c\u00e1lculo de la distancia se basa en la ubicaci\u00f3n geogr\u00e1fica en tiempo real del usuario. SQL++ admite la definici\u00f3n de UDF en JavaScript para realizar l\u00f3gica personalizada en las consultas.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-13094\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/04\/image_2022-04-20_102207935-504x1024.png\" alt=\"Map shwoing searhc for local points of interest\" width=\"504\" height=\"1024\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/image_2022-04-20_102207935-504x1024.png 504w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/image_2022-04-20_102207935-148x300.png 148w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/image_2022-04-20_102207935-300x610.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/image_2022-04-20_102207935-10x20.png 10w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/image_2022-04-20_102207935.png 519w\" sizes=\"auto, (max-width: 504px) 100vw, 504px\" \/><\/p>\n<h2><span style=\"font-weight: 400\">C\u00e1lculo de distancias a partir de coordenadas GPS<\/span><\/h2>\n<p><span style=\"font-weight: 400\">Hay muchas formas de calcular la distancia entre dos conjuntos de coordenadas GPS. En este ejemplo, calcularemos la distancia utilizando la funci\u00f3n <\/span><a href=\"https:\/\/en.wikipedia.org\/wiki\/Haversine_formula\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">F\u00f3rmula Haversine<\/span><\/a><span style=\"font-weight: 400\">. Proporciona la distancia aproximada entre dos coordenadas GPS considerando la trayectoria como una esfera en lugar de una distancia en l\u00ednea recta.<\/span><\/p>\n<p><span style=\"font-weight: 400\">En este ejemplo se muestra c\u00f3digo JavaScript para calcular distancias geogr\u00e1ficas:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:js decode:true\">function gradosARadianes(grados) {\r\n   return grados * Math.PI \/ 180;\r\n }\r\n\r\n function distanciaEnKmEntreCoordenadasTierra(lat1, lon1, lat2, lon2) {\r\n\r\n   var earthRadiusKm = 6371;\r\n   var dLat = gradosToRadians(lat2-lat1);\r\n   var dLon = degreesToRadians(lon2-lon1);\r\n\r\n   lat1 = gradosToRadianes(lat1);\r\n   lat2 = degreesToRadians(lat2);\r\n\r\n   var a = Math.sin(dLat\/2) * Math.sin(dLat\/2) +\r\n           Math.sin(dLon\/2) * Math.sin(dLon\/2) * Math.cos(lat1) * Math.cos(lat2);\r\n   var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));\r\n   return radioTierraKm * c;\r\n}<\/pre>\n<p><span style=\"font-weight: 400\">Definimos dos funciones JavaScript: una que realiza la conversi\u00f3n entre grados y radianes y otra que calcula la distancia en kil\u00f3metros entre las coordenadas GPS de la otra funci\u00f3n.<\/span><\/p>\n<h2><span style=\"font-weight: 400\">Importaci\u00f3n de UDFs a Couchbase<\/span><\/h2>\n<p><span style=\"font-weight: 400\">Estas funciones JavaScript pueden importarse ahora a Couchbase utilizando la funci\u00f3n <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/createfunction.html#create-function-external\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">API REST<\/span><\/a><span style=\"font-weight: 400\">como se muestra a continuaci\u00f3n con el <\/span><i><span style=\"font-weight: 400\">rizo <\/span><\/i><span style=\"font-weight: 400\">mando:<\/span><\/p>\n<pre class=\"wrap:true trim-whitespace:false lang:sh decode:true\">curl -v -X POST https:\/\/localhost:8093\/evaluator\/v1\/libraries\/math -u : -d 'function degreesToRadians(degrees) {\r\n  return grados * Math.PI \/ 180;\r\n  }\r\n  function distanciaEnKmEntreCoordenadasTierra(lat1, lon1, lat2, lon2) {\r\n  var earthRadiusKm = 6371;\r\n  var dLat = gradosToRadianes(lat2-lat1);\r\n  var dLon = gradosToRadians(lon2-lon1);\r\n  lat1 = gradosToRadianes(lat1);\r\n  lat2 = grados a radianes(lat2);\r\n  var a = Math.sin(dLat\/2) * Math.sin(dLat\/2) +\r\n    Math.sin(dLon\/2) * Math.sin(dLon\/2) * Math.cos(lat1) * Math.cos(lat2);\r\n  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));\r\n  return radioTierraKm * c;\r\n}'<\/pre>\n<p><span style=\"font-weight: 400\">Despu\u00e9s de este paso, la UDF se puede definir en la consola web de <strong>Editor de consultas<\/strong>:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:tsql decode:true\">CREATE FUNCTION degreesToRadians(a) LANGUAGE JAVASCRIPT AS \"degreesToRadians\" AT \"math\"\r\n\r\nCREATE FUNCTION distanciaEnKmEntreCoordenadasTierra(lat1, lon1, lat2, lon2) LANGUAGE JAVASCRIPT AS \"distanciaEnKmEntreCoordenadasTierra\" AT \"math\"<\/pre>\n<p><span style=\"font-weight: 400\">Aqu\u00ed, el <\/span><i><span style=\"font-weight: 400\">matem\u00e1ticas<\/span><\/i><span style=\"font-weight: 400\"> hace referencia al c\u00f3digo JavaScript <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-rest-api\/functions.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">biblioteca<\/span><\/a><span style=\"font-weight: 400\"> que creamos para evaluar la UDF.<\/span><\/p>\n<p><span style=\"font-weight: 400\">La UDF puede probarse ahora con coordenadas GPS de muestra en SQL++ utilizando la funci\u00f3n <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/execfunction.html\" target=\"_blank\" rel=\"noopener\"><i><span style=\"font-weight: 400\">Ejecute <\/span><\/i><span style=\"font-weight: 400\">Funci\u00f3n<\/span><\/a><span style=\"font-weight: 400\"> como se muestra a continuaci\u00f3n<\/span><\/p>\n<pre class=\"decode-attributes:false lang:default decode:true\">EXECUTE FUNCTION distanciaEnKmEntreCoordenadasTierra(51.5, 0, 38.8, -77.1)<\/pre>\n<p><span style=\"font-weight: 400\">Podemos observar que la funci\u00f3n funciona seg\u00fan lo previsto cuando proporcionamos manualmente las coordenadas GPS a la funci\u00f3n.<\/span><\/p>\n<h2><span style=\"font-weight: 400\">Conexi\u00f3n de la UDF a los datos de Couchbase<\/span><\/h2>\n<p><span style=\"font-weight: 400\">En el <em>viaje-muestra<\/em> de datos, tenemos las coordenadas GPS del <\/span><i><span style=\"font-weight: 400\">hitos <\/span><\/i><span style=\"font-weight: 400\">y <\/span><i><span style=\"font-weight: 400\">aeropuertos <\/span><\/i><span style=\"font-weight: 400\">junto con otros lugares de inter\u00e9s como <\/span><i><span style=\"font-weight: 400\">hoteles<\/span><\/i><span style=\"font-weight: 400\">.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Podemos integrarlas en nuestras consultas como la siguiente:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:tsql decode:true\">SELECT distanceInKmBetweenEarthCoordinates(a.geo.lat, a.geo.lon, 51.509865, -0.118092) AS distance,\r\n      a.airportname,\r\n      a.ciudad\r\nFROM `viajes-muestra`.inventario.aeropuerto a\r\nORDER BY distancia ASC\r\nLIMIT 10;<\/pre>\n<p><span style=\"font-weight: 400\">Esta consulta devuelve una lista de los diez aeropuertos m\u00e1s cercanos a la ubicaci\u00f3n del usuario (<\/span><i><span style=\"font-weight: 400\">51.509865, -0.118092<\/span><\/i><span style=\"font-weight: 400\">). Proporcionamos la latitud (<\/span><i><span style=\"font-weight: 400\">a.geo.lat<\/span><\/i><span style=\"font-weight: 400\">) y la longitud (<\/span><i><span style=\"font-weight: 400\">a.geo.lon<\/span><\/i><span style=\"font-weight: 400\">)<\/span> <span style=\"font-weight: 400\">campos incrustados en los documentos utilizando la potencia de SQL++.<\/span><\/p>\n<pre class=\"decode-attributes:false lang:js decode:true\">[\r\n   {\r\n     \"airportname\": \"Todos los aeropuertos\",\r\n     \"city\": \"Londres\",\r\n     \"distance\": 0.6998675034052988\r\n   },\r\n   {\r\n     \"airportname\": \"Waterloo International\",\r\n     \"city\": \"London\",\r\n     \"distance\": 0.7880158040048914\r\n   },\r\n   {\r\n     \"airportname\": \"London St Pancras\",\r\n     \"city\": \"London\",\r\n     \"distance\": 2.289359875405007\r\n   },\r\n   {\r\n     \"airportname\": \"Euston Station\",\r\n     \"city\": \"London\",\r\n     \"distance\": 2.30782110865356\r\n   },\r\n   {\r\n     \"airportname\": \"Estaci\u00f3n de tren de St Pancras\",\r\n     \"city\": \"London\",\r\n     \"distance\": 2.582290289682563\r\n   },\r\n   {\r\n     \"airportname\": \"Paddington Station\",\r\n     \"city\": \"London\",\r\n     \"distance\": 4.069442660124984\r\n   },\r\n   {\r\n     \"airportname\": \"London Heliport\",\r\n     \"city\": \"London\",\r\n     \"distance\": 6.062824964656381\r\n   },\r\n   {\r\n     \"airportname\": \"Elstree\",\r\n     \"city\": \"Elstree\",\r\n     \"distance\": 8.735152174563803\r\n   },\r\n   {\r\n     \"airportname\": \"ciudad\",\r\n     \"city\": \"London\",\r\n     \"distance\": 12.009592036043564\r\n   },\r\n   {\r\n     \"airportname\": \"Londres - Kings Cross\",\r\n     \"city\": \"London\",\r\n     \"distance\": 16.891716659500467\r\n   }\r\n ]<\/pre>\n<p><span style=\"font-weight: 400\">Del mismo modo, podemos calcular los puntos de inter\u00e9s alrededor del usuario utilizando la funci\u00f3n <\/span><i><span style=\"font-weight: 400\">hito <\/span><\/i><span style=\"font-weight: 400\">recogida a una distancia cada vez mayor del usuario:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:tsql decode:true\">SELECT distanceInKmBetweenEarthCoordinates(l.geo.lat, l.geo.lon, 51.509865, -0.118092) AS distance,\r\n      l.actividad,\r\n      l.ciudad\r\n      l.contenido\r\nFROM `viaje-muestra`.inventario.landmark l\r\nORDER BY distancia ASC\r\nLIMIT 10;<\/pre>\n<p><span style=\"font-weight: 400\">Resultados de la consulta mostrando puntos de referencia cercanos:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:js decode:true\">[\r\n {\r\n   \"actividad\": \"ver\",\r\n   \"ciudad\": \"Londres\",\r\n   \"contenido\": \"Somerset House alberga tres galer\u00edas de arte:  El excepcional '''Instituto Courtauld''' exhibe una colecci\u00f3n de arte de los siglos XIX y XX, que incluye conocidas obras de Degas, Matisse y Kandinsky; La Colecci\u00f3n Gilbert presenta una colecci\u00f3n de arte decorativo; y Las Salas del Hermitage, la m\u00e1s reciente incorporaci\u00f3n a Somerset House, acoge exposiciones temporales de obras prestadas por el Museo del Hermitage de San Petersburgo. El patio central se llena de fuentes en verano, pero en invierno se instala una pista de hielo, muy popular, por lo que los visitantes deben reservar con antelaci\u00f3n o esperar mucho tiempo para patinar\",\r\n   \"distancia\": 0.10940067520415872\r\n },\r\n {\r\n   \"actividad\": \"ver\",\r\n   \"ciudad\": \"Londres\",\r\n   \"contenido\": \"La Aguja de Cleopatra tiene su origen en la antigua ciudad [[egipcia]]ia de [[El Cairo\/Heli\u00f3polis|Heli\u00f3polis]], en el Templo de Atum, pero los romanos la trasladaron a [[Alejandr\u00eda]] en el a\u00f1o 12 a.C..  En 1819, el virrey Mehemet Ali regal\u00f3 la Aguja de Cleopatra a los brit\u00e1nicos, en conmemoraci\u00f3n de las victorias militares en Egipto, pero permaneci\u00f3 en Alejandr\u00eda hasta 1877, cuando se organiz\u00f3 el transporte para llevarla a Londres.  En el viaje, el barco zozobr\u00f3 en una tormenta, matando a seis miembros de la tripulaci\u00f3n.  Se crey\u00f3 que la Aguja de Cleopatra se hab\u00eda perdido, pero unos arrastreros espa\u00f1oles la encontraron a flote unos d\u00edas despu\u00e9s y, tras algunas reparaciones, lleg\u00f3 a Londres el 21 de enero de 1878. El obelisco est\u00e1 flanqueado por dos falsas esfinges, que muestran los efectos de los bombardeos de Londres durante la II Guerra Mundial.  En la actualidad, la Aguja de Cleopatra muestra cierto desgaste por la exposici\u00f3n al clima h\u00famedo de Londres\",\r\n   \"distancia\": 0.2153782246329736\r\n },\r\n {\r\n   \"actividad\": \"comprar\",\r\n   \"ciudad\": \"Londres\",\r\n   \"contenido\": \"Venta diaria de libros de segunda mano cerca de la orilla del T\u00e1mesis. Un lugar agradable para simplemente curiosear libros (cl\u00e1sicos y modernos), mapas y grabados\",\r\n   \"distance\": 0.329776385402355\r\n },\r\n {\r\n   \"actividad\": \"ver\",\r\n   \"ciudad\": \"Londres\",\r\n   \"contenido\": \"[[Londres]] (en [[Londres\/Covent Garden|Covent Garden]])\",\r\n   \"distancia\": 0.34889537479151833\r\n },\r\n {\r\n   \"actividad\": \"ver\",\r\n   \"ciudad\": \"Londres\",\r\n   \"content\": \"La zona de skate m\u00e1s famosa y popular de Londres, situada en parte debajo del Queen Elizabeth Hall a lo largo de Queen's Walk y el T\u00e1mesis.  Tambi\u00e9n popular entre grafiteros, BMXers, etc.\",\r\n   \"distance\": 0.36487940944981834\r\n },\r\n {\r\n   \"actividad\": \"ver\",\r\n   \"ciudad\": \"Londres\",\r\n   \"contenido\": \"Escondido bajo el puente de Waterloo, el BFI Southbank, antes conocido como National Film Theatre, se presenta como el hogar del cine y cuenta con tres pantallas en las que se proyectan pel\u00edculas cl\u00e1sicas (incluidas mudas), en lenguas extranjeras y menos convencionales. Recientemente remodelado, cuenta con una nueva entrada por Theatre Alley, una tienda dedicada al cine, un espacio de exposiciones interactivas y un excelente bar-restaurante en la parte trasera. Los visitantes tambi\u00e9n pueden acceder a la Mediateca, donde podr\u00e1n recorrer gratuitamente el extenso archivo de cine y televisi\u00f3n del BFI.  Bar y restaurante geniales. Las entradas suelen estar disponibles en el momento\",\r\n   \"distancia\": 0.378692262237853\r\n },\r\n {\r\n   \"actividad\": \"ver\",\r\n   \"ciudad\": \"Londres\",\r\n   \"contenido\": \"Local musical que acoge actuaciones diarias. | image=Queen Elizabeth Hall.jpg\",\r\n   \"distance\": 0.3859430181613397\r\n },\r\n {\r\n   \"actividad\": \"bebida\",\r\n   \"ciudad\": \"Londres\",\r\n   \"contenido\": \"El ant\u00eddoto a los bares gay: ambiente de pub y buena m\u00fasica. | image=The Retro Bar.jpg\",\r\n   \"distance\": 0.39732030942983415\r\n },\r\n {\r\n   \"actividad\": \"ver\",\r\n   \"ciudad\": \"Londres\",\r\n   \"contenido\": \"Tres grandes auditorios, el Olivier, el Lyttelton y el Cottesloe. El teatro Olivier es el m\u00e1s grande, con un escenario abierto y un auditorio en forma de abanico a su alrededor. De este modo, todos los asientos ofrecen una buena visi\u00f3n. Aqu\u00ed se representan la mayor\u00eda de las producciones m\u00e1s \"populares\", ya que el espacio es mucho mayor que en la mayor\u00eda de los teatros. El teatro Lyttelton es m\u00e1s tradicional, con un arco procenium con buenas vistas desde la mayor\u00eda de los asientos. El Cottesloe es un peque\u00f1o estudio con capacidad para unas 400 personas. Algunas entradas estar\u00e1n disponibles el mismo d\u00eda de la funci\u00f3n, ya sean localidades de d\u00eda (hay que llegar antes de las 9.30 y hacer cola) o de espera (hay que llegar antes de las 18.00 y hacer cola), o se pueden comprar por Internet. Los espect\u00e1culos m\u00e1s populares, especialmente los que se representan en Navidad en el Olivier, se agotan con meses de antelaci\u00f3n. Las entradas para el National Theatre suelen ser m\u00e1s baratas que para la mayor\u00eda de los teatros. Tambi\u00e9n existe la temporada \"\u00a310 Travelex\" en verano, que ofrece un gran n\u00famero de entradas (m\u00e1s de 100.000 al a\u00f1o) a 10 libras. Es necesario reservar con antelaci\u00f3n. En el vest\u00edbulo del teatro Lyttelton tambi\u00e9n hay un espacio de exposiciones que suele albergar populares muestras fotogr\u00e1ficas. En el vest\u00edbulo de la planta baja se suele tocar jazz gratis por la noche. En verano hay un festival diario gratuito al aire libre de actuaciones, m\u00fasica, comedia y cabaret conocido como Watch This Space. Hay tumbonas (y c\u00e9sped artificial) a disposici\u00f3n de los espectadores. Exposiciones gratuitas. Visitas entre bastidores 5 \u00a3 (https:\/\/www.nationaltheatrelondon.com\/tickets\/)\",\r\n   \"distancia\": 0.42625112040817054\r\n },\r\n {\r\n   \"actividad\": \"bebida\",\r\n   \"ciudad\": \"Londres\",\r\n   \"contenido\": \"Eventos musicales nocturnos gratuitos.  El mejor lugar para probar electro underground, indie, dub-step y mucho m\u00e1s\",\r\n   \"distance\": 0.4323026974543284\r\n }\r\n]<\/pre>\n<p><span style=\"font-weight: 400\">Si ejecutamos estas consultas para varios usuarios al mismo tiempo, podr\u00edamos encontrarnos con problemas de rendimiento, ya que estamos utilizando los recursos inform\u00e1ticos que forman parte del cl\u00faster de Couchbase.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">En tales escenarios, Couchbase Analytics podr\u00eda reducir el impacto en tu cluster. <\/span><span style=\"font-weight: 400\">Couchbase Analytics est\u00e1 dise\u00f1ado para ejecutar eficientemente consultas complejas sobre muchos registros. Las consultas complejas pueden incluir grandes operaciones ad hoc de uni\u00f3n, conjunto, agregaci\u00f3n y agrupaci\u00f3n, cualquiera de las cuales puede dar lugar a consultas de larga duraci\u00f3n, alto uso de CPU, alto consumo de memoria o latencia de red excesiva debido a la obtenci\u00f3n de datos y la coordinaci\u00f3n entre nodos.<\/span><\/p>\n<h2><span style=\"font-weight: 400\">Funciones definidas por el usuario con Couchbase Analytics<\/span><\/h2>\n<p><span style=\"font-weight: 400\">Couchbase Analytics nos permite definir y utilizar <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/analytics\/appendix_5_python.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">Funciones definidas por el usuario en Python<\/span><\/a><span style=\"font-weight: 400\"> pero en el momento de redactar este documento requiere que <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/developer-preview\/preview-mode.html#how-do-i-enable-the-developer-preview-mode\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">activar la vista previa para desarrolladores<\/span><\/a><span style=\"font-weight: 400\"> en Couchbase Server. Esto se puede hacer con el siguiente comando:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:sh decode:true\">$ \/opt\/couchbase\/bin\/couchbase-cli enable-developer-preview - --enable\r\n  --enable -c localhost:8091 -u  -p<\/pre>\n<p><span style=\"font-weight: 400\">El siguiente paso es crear un paquete Python, localmente, en el entorno de desarrollo con el UDF de Python. En este caso, el UDF es un m\u00e9todo para calcular la distancia entre dos coordenadas GPS.<\/span><\/p>\n<pre class=\"decode-attributes:false lang:python decode:true\"># distancia.py\r\nfrom geopy import distancia\r\n\r\nclase c\u00e1lculo_distancia:\r\n   def calcular_distancia(self, lat1, lon1, lat2, lon2) -&gt; float:\r\n       \"\"\"Calcula la distancia usando la distancia geod\u00e9sica\"\"\"\"\r\n       return distancia.distancia((lat1, lon1), (lat2, lon2)).km<\/pre>\n<p><span style=\"font-weight: 400\">Aqu\u00ed calculamos el <\/span><a href=\"https:\/\/en.wikipedia.org\/wiki\/Geodesics_on_an_ellipsoid\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">distancia geod\u00e9sica<\/span><\/a><span style=\"font-weight: 400\"> (la distancia m\u00e1s corta entre puntos a lo largo de una trayectoria curva) entre las dos coordenadas GPS con la ayuda de una biblioteca, <\/span><a href=\"https:\/\/geopy.readthedocs.io\/\" target=\"_blank\" rel=\"noopener\"><i><span style=\"font-weight: 400\">geopy<\/span><\/i><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<h3><span style=\"font-weight: 400\">Empaquetado de la UDF<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Para empaquetar la biblioteca, utilizamos un paquete <\/span><a href=\"https:\/\/shiv.readthedocs.io\/en\/latest\/\" target=\"_blank\" rel=\"noopener\"><i><span style=\"font-weight: 400\">shiv<\/span><\/i><\/a> <span style=\"font-weight: 400\">que puede empaquetar el c\u00f3digo junto con sus requisitos para cualquier plataforma. Aqu\u00ed, estamos utilizando Linux como Couchbase Server se ejecuta en un entorno Linux dentro de Docker.<\/span><\/p>\n<pre class=\"decode-attributes:false lang:sh decode:true\">shiv -o distancia.pyz --sitio-paquetes . --platform manylinux2010_x86_64 --python-version 39 --only-binary=:all: geopy<\/pre>\n<p><span style=\"font-weight: 400\">Para subir este paquete binario con el UDF a Couchbase, tenemos que utilizar el comando <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/analytics\/rest-library.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">API REST<\/span><\/a><span style=\"font-weight: 400\"> para el servicio Analytics.\u00a0<\/span><\/p>\n<pre class=\"decode-attributes:false lang:sh decode:true\">curl -X POST -u : -F \"type=python\" -F \"data=@.\/distance.pyz\" localhost:8095\/analytics\/library\/Default\/pylib<\/pre>\n<p><span style=\"font-weight: 400\">Esto carga el UDF empaquetado en el archivo <\/span><i><span style=\"font-weight: 400\">pylib<\/span><\/i><span style=\"font-weight: 400\"> biblioteca en el <\/span><i><span style=\"font-weight: 400\">por defecto <\/span><\/i><span style=\"font-weight: 400\">alcance (anteriormente <\/span><span style=\"font-weight: 400\">universo de datos<\/span><span style=\"font-weight: 400\">) del entorno Analytics. Ahora podemos definir la UDF en el <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/analytics\/run-query.html#Using_analytics_workbench\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">Workbench de an\u00e1lisis<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Esta definici\u00f3n indica que estamos definiendo una UDF llamada <\/span><i><span style=\"font-weight: 400\">distancia_en_km <\/span><\/i><span style=\"font-weight: 400\">que puede llamarse desde la funci\u00f3n Python <\/span><i><span style=\"font-weight: 400\">calcular_distancia <\/span><\/i><span style=\"font-weight: 400\">definido en la clase <\/span><i><span style=\"font-weight: 400\">c\u00e1lculo_distancia<\/span><\/i><span style=\"font-weight: 400\"> dentro del m\u00f3dulo Python <\/span><i><span style=\"font-weight: 400\">distancia.<\/span><\/i><\/p>\n<pre class=\"decode-attributes:false lang:tsql decode:true\">CREATE ANALYTICS FUNCTION distancia_en_km(lat1, lon1, lat2, lon2) AS \"distancia\",\r\n  \"calculo_distancia.calcular_distancia\" AT pylib;<\/pre>\n<p><span style=\"font-weight: 400\">Ahora podemos utilizar la UDF en nuestras consultas de Analytics del mismo modo que utilizamos la UDF en nuestras consultas de SQL++.<\/span><\/p>\n<pre class=\"decode-attributes:false lang:tsql decode:true\">SELECT distancia_en_km(51.5, 0, 38.8, -77.1) AS \"distancia\"\r\n\r\nRESULTADO\r\n[\r\n {\r\n   \"distancia\": 5933.5299530300545\r\n }\r\n]<\/pre>\n<h3><span style=\"font-weight: 400\">Asignaci\u00f3n de datos del servicio de datos al servicio de an\u00e1lisis<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Para consultar los datos en el Servicio de Datos desde el Servicio de An\u00e1lisis, necesitamos <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/analytics\/manage-datasets.html#mapping-collections-from-the-data-service\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">mapa<\/span><\/a><span style=\"font-weight: 400\"> el <\/span><i><span style=\"font-weight: 400\">viaje-muestra<\/span><\/i><span style=\"font-weight: 400\"> en Analytics que crea una copia sombra en tiempo real de los datos en el servicio de datos de Analytics. Para este ejemplo, necesitamos asignar las colecciones con datos geogr\u00e1ficos, a saber, el <\/span><i><span style=\"font-weight: 400\">hito, aeropuerto <\/span><\/i><span style=\"font-weight: 400\">y<\/span><i><span style=\"font-weight: 400\"> hotel<\/span><\/i><span style=\"font-weight: 400\"> colecciones del \u00e1mbito del inventario en el<\/span><i><span style=\"font-weight: 400\"> viaje-muestra<\/span><\/i><span style=\"font-weight: 400\"> cubo.<\/span><\/p>\n<h3><span style=\"font-weight: 400\">Ejecuci\u00f3n de la UDF de an\u00e1lisis con datos de Couchbase<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Ahora, podemos ejecutar las mismas consultas que ejecut\u00e1bamos antes en SQL++ pero con el Servicio Analytics. S\u00f3lo ha cambiado el nombre de la UDF. El resto de la interfaz es similar a la que ten\u00edamos con las consultas SQL++. Los resultados tambi\u00e9n ser\u00e1n similares a los anteriores.<\/span><\/p>\n<pre class=\"decode-attributes:false lang:tsql decode:true\">SELECT distancia_en_km(a.geo.lat, a.geo.lon, 51.509865, -0.118092) AS distancia,\r\n      a.airportname,\r\n      a.ciudad\r\nFROM `viajes-muestra`.inventario.aeropuerto a\r\nORDER BY distancia ASC\r\nLIMIT 10;\r\n\r\nSELECT distancia_en_km(l.geo.lat, l.geo.lon, 51.509865, -0.118092) AS distancia,\r\n      l.actividad\r\n      l.ciudad\r\n      l.contenido\r\nFROM `viaje-muestra`.inventario.hito l\r\nORDER BY distancia ASC\r\nLIMIT 10;<\/pre>\n<p><span style=\"font-weight: 400\">Este enfoque es adecuado cuando queremos ejecutar estas consultas sin afectar al <\/span><i><span style=\"font-weight: 400\">Servicio de datos<\/span><\/i><span style=\"font-weight: 400\"> que se utiliza habitualmente para nuestros datos transaccionales. Los datos se sincronizan entre <\/span><i><span style=\"font-weight: 400\">Datos <\/span><\/i><span style=\"font-weight: 400\">y el<\/span><i><span style=\"font-weight: 400\"> Servicio de an\u00e1lisis <\/span><\/i><span style=\"font-weight: 400\">internamente en tiempo real en Couchbase.<\/span><\/p>\n<h2><span style=\"font-weight: 400\">Resumen<\/span><\/h2>\n<p><span style=\"font-weight: 400\">En esta entrada de blog, has aprendido a crear una Funci\u00f3n Definida por el Usuario (UDF) en JavaScript que calcula distancias entre dos coordenadas GPS. Has visto c\u00f3mo importar la UDF a Couchbase y luego integrarla en una consulta SQL++ para potenciar aplicaciones que podr\u00edan proporcionar puntos de inter\u00e9s alrededor de un usuario. Tambi\u00e9n vimos c\u00f3mo puedes realizar el mismo c\u00e1lculo de distancia en un UDF basado en Python usando el servicio Analytics para reducir el impacto en tu cluster transaccional de Couchbase.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Para m\u00e1s informaci\u00f3n y referencias, consulte los siguientes recursos:<\/span><\/p>\n<ul>\n<li style=\"list-style-type: none\">\n<ul>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/www.couchbase.com\/blog\/es\/n1ql-user-defined-functions\/\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">SQL++ ya admite funciones definidas por el usuario<\/span><\/a><span style=\"font-weight: 400\">\u00a0(Blog)<\/span><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/docs.couchbase.com\/java-sdk\/current\/ref\/travel-app-data-model.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">Aplicaci\u00f3n de ejemplo Couchbase Travel<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/createfunction.html#create-function-external\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400\">API REST de Couchbase para crear funciones<\/span><\/a><span style=\"font-weight: 400\"> (Docs)<\/span><\/li>\n<li style=\"font-weight: 400\"><a href=\"https:\/\/docs.couchbase.com\/server\/current\/analytics\/appendix_5_python.html\" target=\"_blank\" rel=\"noopener\">Creaci\u00f3n de UDFs Python en Couchbase Analytics Service<\/a> (Docs)<\/li>\n<\/ul>\n<\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>SQL++ queries can access data stored in your Couchbase cluster in a variety of ways. There are situations where having the business logic as part of your data queries can also be beneficial. SQL++ supports this with User Defined Functions [&hellip;]<\/p>","protected":false},"author":80878,"featured_media":13093,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[2294,1816,8683,9327,9139,1812],"tags":[1543,8911],"ppma_author":[9543],"class_list":["post-13092","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-analytics","category-couchbase-server","category-geospatial","category-javascript","category-python","category-n1ql-query","tag-javascript","tag-udf"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Creating Python and JavaScript User Defined Functions For Geospatial Queries - The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"Create User Defined Functions UDFs in Python and JavaScript to run geospatial queries in Couchbase Analytics and SQL++\" \/>\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\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Creating Python and JavaScript User Defined Functions For Geospatial Queries\" \/>\n<meta property=\"og:description\" content=\"Create User Defined Functions UDFs in Python and JavaScript to run geospatial queries in Couchbase Analytics and SQL++\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/es\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-04-20T17:22:45+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T06:34:37+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/couchbase-analytics-sql-user-defined-functions-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1920\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Nithish Raghunandanan\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nithish Raghunandanan\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/\"},\"author\":{\"name\":\"nithishr\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c5a843d75ad78b5b698f59ca6d123af2\"},\"headline\":\"Creating Python and JavaScript User Defined Functions For Geospatial Queries\",\"datePublished\":\"2022-04-20T17:22:45+00:00\",\"dateModified\":\"2025-06-14T06:34:37+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/\"},\"wordCount\":1127,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/couchbase-analytics-sql-user-defined-functions-scaled.jpg\",\"keywords\":[\"javascript\",\"User Defined Function (UDF)\"],\"articleSection\":[\"Couchbase Analytics\",\"Couchbase Server\",\"Geospatial\",\"JavaScript\",\"Python\",\"SQL++ \/ N1QL Query\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/\",\"name\":\"Creating Python and JavaScript User Defined Functions For Geospatial Queries - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/couchbase-analytics-sql-user-defined-functions-scaled.jpg\",\"datePublished\":\"2022-04-20T17:22:45+00:00\",\"dateModified\":\"2025-06-14T06:34:37+00:00\",\"description\":\"Create User Defined Functions UDFs in Python and JavaScript to run geospatial queries in Couchbase Analytics and SQL++\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/couchbase-analytics-sql-user-defined-functions-scaled.jpg\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/couchbase-analytics-sql-user-defined-functions-scaled.jpg\",\"width\":2560,\"height\":1920,\"caption\":\"Create user defined functions in Python and JavaScript\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Creating Python and JavaScript User Defined Functions For Geospatial Queries\"}]},{\"@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\/c5a843d75ad78b5b698f59ca6d123af2\",\"name\":\"nithishr\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/63270a592008f9080fe48b7652fe559f\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/03\/image-4.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/03\/image-4.png\",\"caption\":\"nithishr\"},\"description\":\"Nithish is an engineer who loves to build products that solve real-world problems in short spans of time. He has experienced different areas of the industry having worked in diverse companies in Germany and India. Apart from work, he likes to travel and interact and engage with the tech community through Meetups &amp; Hackathons. In his free time, he likes to try stuff out by hacking things together.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/es\/author\/nithishr\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Creating Python and JavaScript User Defined Functions For Geospatial Queries - The Couchbase Blog","description":"Create User Defined Functions UDFs in Python and JavaScript to run geospatial queries in Couchbase Analytics and SQL++","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\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/","og_locale":"es_MX","og_type":"article","og_title":"Creating Python and JavaScript User Defined Functions For Geospatial Queries","og_description":"Create User Defined Functions UDFs in Python and JavaScript to run geospatial queries in Couchbase Analytics and SQL++","og_url":"https:\/\/www.couchbase.com\/blog\/es\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/","og_site_name":"The Couchbase Blog","article_published_time":"2022-04-20T17:22:45+00:00","article_modified_time":"2025-06-14T06:34:37+00:00","og_image":[{"width":2560,"height":1920,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/couchbase-analytics-sql-user-defined-functions-scaled.jpg","type":"image\/jpeg"}],"author":"Nithish Raghunandanan","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Nithish Raghunandanan","Est. reading time":"11 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/"},"author":{"name":"nithishr","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c5a843d75ad78b5b698f59ca6d123af2"},"headline":"Creating Python and JavaScript User Defined Functions For Geospatial Queries","datePublished":"2022-04-20T17:22:45+00:00","dateModified":"2025-06-14T06:34:37+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/"},"wordCount":1127,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/couchbase-analytics-sql-user-defined-functions-scaled.jpg","keywords":["javascript","User Defined Function (UDF)"],"articleSection":["Couchbase Analytics","Couchbase Server","Geospatial","JavaScript","Python","SQL++ \/ N1QL Query"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/","url":"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/","name":"Creating Python and JavaScript User Defined Functions For Geospatial Queries - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/couchbase-analytics-sql-user-defined-functions-scaled.jpg","datePublished":"2022-04-20T17:22:45+00:00","dateModified":"2025-06-14T06:34:37+00:00","description":"Create User Defined Functions UDFs in Python and JavaScript to run geospatial queries in Couchbase Analytics and SQL++","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/couchbase-analytics-sql-user-defined-functions-scaled.jpg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/04\/couchbase-analytics-sql-user-defined-functions-scaled.jpg","width":2560,"height":1920,"caption":"Create user defined functions in Python and JavaScript"},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/creating-python-and-javascript-user-defined-functions-for-geospatial-queries\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Creating Python and JavaScript User Defined Functions For Geospatial Queries"}]},{"@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\/c5a843d75ad78b5b698f59ca6d123af2","name":"nithishr","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/63270a592008f9080fe48b7652fe559f","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/03\/image-4.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/03\/image-4.png","caption":"nithishr"},"description":"Nithish es un ingeniero al que le encanta crear productos que resuelvan problemas del mundo real en poco tiempo. Ha trabajado en diferentes \u00e1reas de la industria en diversas empresas de Alemania y la India. Aparte del trabajo, le gusta viajar e interactuar con la comunidad tecnol\u00f3gica a trav\u00e9s de Meetups y Hackathons. En su tiempo libre, le gusta probar cosas hacke\u00e1ndolas.","url":"https:\/\/www.couchbase.com\/blog\/es\/author\/nithishr\/"}]}},"authors":[{"term_id":9543,"user_id":80878,"is_guest":0,"slug":"nithishr","display_name":"Nithish Raghunandanan","avatar_url":{"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/03\/image-4.png","url2x":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/03\/image-4.png"},"author_category":"","last_name":"Raghunandanan","first_name":"Nithish","job_title":"","user_url":"","description":"Nithish es un ingeniero al que le encanta crear productos que resuelvan problemas del mundo real en poco tiempo. Ha trabajado en diferentes \u00e1reas de la industria en diversas empresas de Alemania y la India. Aparte del trabajo, le gusta viajar e interactuar con la comunidad tecnol\u00f3gica a trav\u00e9s de Meetups y Hackathons. En su tiempo libre, le gusta probar cosas hacke\u00e1ndolas."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/13092","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\/80878"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/comments?post=13092"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/13092\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media\/13093"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media?parent=13092"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/categories?post=13092"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/tags?post=13092"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/ppma_author?post=13092"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}