{"id":2854,"date":"2017-02-28T08:41:20","date_gmt":"2017-02-28T16:41:20","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=2854"},"modified":"2025-06-13T21:40:21","modified_gmt":"2025-06-14T04:40:21","slug":"graphql-server-node-couchbase-ottoman-spatial-view","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/pt\/graphql-server-node-couchbase-ottoman-spatial-view\/","title":{"rendered":"Servidor Graphql com node e couchbase, ottoman e visualiza\u00e7\u00e3o espacial"},"content":{"rendered":"<p><em><a href=\"https:\/\/www.linkedin.com\/in\/jm8nav\"><span class=\"no-underline\">Jos\u00e9 Navarro<\/span><\/a> \u00e9 um desenvolvedor full stack na FAMOCO em Bruxelas, B\u00e9lgica. Ele tem trabalhado nos \u00faltimos 3 anos como desenvolvedor web <a href=\"https:\/\/github.com\/jmn8718\">desenvolvedor<\/a> com Node.js, Java, AngularJS e ReactJS, e tem grande interesse em desenvolvimento web e tecnologias m\u00f3veis.<\/em><\/p>\n<p>Vamos desenvolver um <u><a href=\"https:\/\/graphql.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">Graphql<\/a><\/u>\u00a0servidor em nodejs com express. Graphql \u00e9 uma linguagem de consulta para APIs, foi desenvolvida pelo Facebook e lan\u00e7ada em 2015. Ela foi projetada para criar aplicativos de clientes fornecendo uma sintaxe e um sistema intuitivos e flex\u00edveis para descrever seus requisitos de dados e intera\u00e7\u00f5es. Uma das maiores diferen\u00e7as em rela\u00e7\u00e3o \u00e0s APIs REST \u00e9 que voc\u00ea tem apenas um ponto de extremidade de entrada para todos os recursos, em vez de um ponto de extremidade para cada recurso; e com o graphql voc\u00ea especifica os atributos que deseja para cada solicita\u00e7\u00e3o, em vez de receber o que quer que o servi\u00e7o da API REST retorne, para que possamos ter certeza de que temos todos os dados de que precisamos e reduzir o tamanho de nossas solicita\u00e7\u00f5es.<\/p>\n<p>O Facebook o utiliza h\u00e1 alguns anos em seu aplicativo m\u00f3vel, por exemplo, no aplicativo para iOS, e a vers\u00e3o antiga do aplicativo m\u00f3vel ainda funciona sem problemas porque o graphql n\u00e3o mudou, porque \u00e9 um ponto de extremidade com o mesmo esquema, o que provavelmente n\u00e3o seria poss\u00edvel com as APIs REST, porque quando voc\u00ea lan\u00e7a uma nova vers\u00e3o da API, seu ponto de extremidade provavelmente vai mudar, de modo que os clientes precisam se adaptar ao novo ponto de extremidade e aos dados. Al\u00e9m disso <u><a href=\"https:\/\/developer.github.com\/early-access\/graphql\/\" target=\"_blank\" rel=\"noopener noreferrer\">Github<\/a><\/u>\u00a0abrir seu servidor graphql, para que os usu\u00e1rios possam consultar seus servi\u00e7os usando graphql, em vez dos servi\u00e7os de APIs REST...<\/p>\n<p>Com o servidor, vamos consultar e criar <strong>Locais<\/strong>. Para armazenar os dados, usaremos o couchbase e as exibi\u00e7\u00f5es espaciais para consultar os locais por sua localiza\u00e7\u00e3o geogr\u00e1fica. Escrevi um artigo anterior <u><a href=\"https:\/\/www.couchbase.com\/blog\/pt\/develop-a-rest-api-with-couchbase-ottoman-nodejs-hapijs\/\" target=\"_blank\" rel=\"noopener noreferrer\">postagem<\/a><\/u>\u00a0sobre o node e o couchbase, portanto, vou pular a configura\u00e7\u00e3o do banco de dados que escrevi na postagem anterior.<\/p>\n<h2>Requisitos<\/h2>\n<p>Voc\u00ea precisa ter instalado em seu computador:<\/p>\n<p>- nodejs<\/p>\n<p>- servidor couchbase<\/p>\n<p>Voc\u00ea pode encontrar o c\u00f3digo na se\u00e7\u00e3o <u><a href=\"https:\/\/github.com\/jmn8718\/node-couchbase-graphql.git\" target=\"_blank\" rel=\"noopener noreferrer\">reposit\u00f3rio do github<\/a><\/u>.<\/p>\n<h2>Vis\u00e3o espacial<\/h2>\n<p>Antes de tudo, precisamos criar a visualiza\u00e7\u00e3o espacial. Vamos para a p\u00e1gina de administra\u00e7\u00e3o, no meu caso <u><a href=\"https:\/\/localhost:8091\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/localhost:8091\/<\/a><\/u>\u00a0e fa\u00e7a login com meu usu\u00e1rio e senha. Em seguida, clique em <strong>Compartimentos de dados<\/strong>\u00a0e criar um bucket, que chamei de <em>graphql<\/em>. Depois disso, clicamos em <strong>Ver<\/strong>e, em seguida, clicamos em <strong>Criar visualiza\u00e7\u00e3o espacial do desenvolvimento<\/strong>e digitamos os valores.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/create_view.png\" alt=\"Create Spatial Development View\" width=\"404\" height=\"301\" \/><\/p>\n<p>Eu usei <em>lugar_por_localiza\u00e7\u00e3o<\/em>\u00a0em ambos <strong>Nome do documento de design<\/strong>\u00a0e <strong>Ver nome<\/strong>. Agora clique em <strong>editar<\/strong>e adicione o seguinte c\u00f3digo<\/p>\n<p><code><br \/>\nfunction (doc) {<\/code><\/p>\n<p>Se (doc._type === 'Place' &amp;&amp; doc.location) {<\/p>\n<p>emit([{<\/p>\n<p>\"type\": \"Ponto\",<\/p>\n<p>\"coordenadas\": [doc.location.lon, doc.location.lat]<\/p>\n<p>}], doc);<\/p>\n<p>}<\/p>\n<p>}<br \/>\ne clique em <strong>Salvar<\/strong>.<\/p>\n<p>Aqui voc\u00ea tamb\u00e9m pode testar a visualiza\u00e7\u00e3o com os documentos no balde.<\/p>\n<h2>Local Modelo<\/h2>\n<p>Para nossos locais, vamos armazenar o nome do local e uma descri\u00e7\u00e3o como string.<\/p>\n<p>Como queremos usar o <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/4.6\/views\/sv-writing-views.html\">SpatialView<\/a> que <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/developers\/\">Couchbase<\/a> fornece, vamos armazenar a localiza\u00e7\u00e3o do local em um objeto chamado *location*, no qual armazenaremos a latitude e a longitude.<\/p>\n<p>Al\u00e9m disso, definiremos por padr\u00e3o a data de cria\u00e7\u00e3o quando adicionarmos o local.<\/p>\n<p><code><br \/>\nconst PlaceModel = ottoman.model('Place', {<\/code><\/p>\n<p>nome: 'string',<\/p>\n<p>descri\u00e7\u00e3o: 'string',<\/p>\n<p>localiza\u00e7\u00e3o: {<\/p>\n<p>lat: 'number',<\/p>\n<p>lon: 'number'<\/p>\n<p>},<\/p>\n<p>criado: {<\/p>\n<p>tipo: 'Date',<\/p>\n<p>padr\u00e3o: Date.now<\/p>\n<p>}<\/p>\n<p>});<br \/>\nPara a consulta espacial, vamos definir uma fun\u00e7\u00e3o que executar\u00e1 uma consulta espacial. Para isso, vamos criar uma consulta espacial usando o pacote couchbase.<\/p>\n<p><code><br \/>\nconst queryByLocation = (bbox = [0, 0, 0, 0], next) =&gt; {<\/code><\/p>\n<p>const query = couchbase.SpatialQuery.from('dev_place_by_location', 'place_by_location').bbox(bbox);<\/p>\n<p>bucket.query(query, next);<\/p>\n<p>}<br \/>\nNa fun\u00e7\u00e3o *from*, precisamos fornecer o *nome do documento de design* e o *nome da visualiza\u00e7\u00e3o*. Em seguida, na bbox (caixa delimitadora), precisamos fornecer a matriz de 4 pontos flutuantes **[ min Longitude , min Latitude , max Longitude , max Latitude ]**.<\/p>\n<p>A \u00faltima etapa \u00e9 executar a consulta no bucket.<\/p>\n<h2>Servidor Graphql<\/h2>\n<p>Vamos usar um servidor express e o pacote express-graphql.<\/p>\n<p>Importamos o esquema do nosso servidor graphql que definiremos mais tarde.<\/p>\n<p><code><br \/>\nconst express = require('express');<\/code><\/p>\n<p>const graphqlHTTP = require('express-graphql');<\/p>\n<p>const PORT = process.env.PORT || 5000;<\/p>\n<p>const schema = require('.\/schemas');<\/p>\n<p>const app = express();<\/p>\n<p>app.use('\/graphql', graphqlHTTP({<\/p>\n<p>esquema: esquema,<\/p>\n<p>graphiql: true,<\/p>\n<p>}));<\/p>\n<p>\/\/ iniciar o servidor<\/p>\n<p>const server = app.listen(PORT, () =&gt; {<\/p>\n<p>console.log(`Server started at ${ server.address().port }`);<\/p>\n<p>});<br \/>\nNo servidor graphql, usaremos a rota *\/graphql*. E vamos definir alguma op\u00e7\u00e3o, como graphiql, que nos fornecer\u00e1 uma interface gr\u00e1fica para executar consultas.<\/p>\n<p>A \u00faltima etapa \u00e9 iniciar nosso servidor expresso.<\/p>\n<h2>Esquemas Graphql<\/h2>\n<p>As consultas e muta\u00e7\u00f5es do Graphql dependem dos esquemas que definimos. Portanto, temos de criar um esquema para o nosso objeto Place.<\/p>\n<p>Primeiro, vamos definir um esquema para <strong>Localiza\u00e7\u00e3o<\/strong>.<\/p>\n<p><code><br \/>\nconst {<\/code><\/p>\n<p>GraphQLObjectType,<\/p>\n<p>GraphQLFloat,<\/p>\n<p>GraphQLNonNull,<\/p>\n<p>} = require('graphql');<\/p>\n<p>const LocationSchema = new GraphQLObjectType({<\/p>\n<p>nome: 'Location',<\/p>\n<p>description: 'Geographical location',<\/p>\n<p>campos: {<\/p>\n<p>lat: {<\/p>\n<p>type: new GraphQLNonNull(GraphQLFloat),<\/p>\n<p>descri\u00e7\u00e3o: 'Latitude',<\/p>\n<p>},<\/p>\n<p>lon: {<\/p>\n<p>type: new GraphQLNonNull(GraphQLFloat),<\/p>\n<p>descri\u00e7\u00e3o: 'Longitude',<\/p>\n<p>},<\/p>\n<p>}<\/p>\n<p>});<\/p>\n<p>module.exports = LocationSchema;<\/p>\n<p>Precisamos importar os tipos de <em>graphql<\/em>\u00a0pacote. Em nosso esquema, podemos definir um nome e uma descri\u00e7\u00e3o. Esses campos s\u00e3o \u00fateis para documentar nossas consultas, para que o usu\u00e1rio possa entender o que o campo significa.<\/p>\n<p>Ent\u00e3o temos que definir <em>campos<\/em>onde especificaremos os campos dentro de nosso esquema; nesse caso, definimos <em>lat<\/em>\u00a0e <em>solit\u00e1rio<\/em>. Em cada campo, temos que especificar o tipo; nesse caso, esses campos s\u00e3o valores float e s\u00e3o obrigat\u00f3rios, portanto, usamos <em>GraphQLNonNull<\/em>\u00a0 e o tipo <em>GraphQLFloat<\/em>. Adicionamos uma descri\u00e7\u00e3o para que possamos saber o que eles significam.<\/p>\n<p>Agora vamos definir o esquema <strong>Local<\/strong>.<\/p>\n<p>Aqui, vamos importar os tipos de <em>graphql<\/em>\u00a0e o esquema <em>Localiza\u00e7\u00e3o<\/em>\u00a0que definimos.<\/p>\n<p><code><br \/>\nconst {<\/code><\/p>\n<p>GraphQLObjectType,<\/p>\n<p>GraphQLString,<\/p>\n<p>GraphQLNonNull,<\/p>\n<p>} = require('graphql');<\/p>\n<p>const LocationSchema = require('.\/location');<\/p>\n<p>const PlaceSchema = new GraphQLObjectType({<\/p>\n<p>nome: 'Place',<\/p>\n<p>description: 'Descri\u00e7\u00e3o do local',<\/p>\n<p>campos: {<\/p>\n<p>id: {<\/p>\n<p>Tipo: GraphQLString,<\/p>\n<p>resolve(place) {<\/p>\n<p>return place._id;<\/p>\n<p>}<\/p>\n<p>},<\/p>\n<p>nome: {<\/p>\n<p>Tipo: GraphQLString,<\/p>\n<p>},<\/p>\n<p>descri\u00e7\u00e3o:{<\/p>\n<p>Tipo: GraphQLString,<\/p>\n<p>},<\/p>\n<p>localiza\u00e7\u00e3o: {<\/p>\n<p>Tipo: LocationSchema,<\/p>\n<p>},<\/p>\n<p>criado: {<\/p>\n<p>Tipo: GraphQLString,<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>});<\/p>\n<p>module.exports = PlaceSchema;<\/p>\n<p>Estamos combinando os campos do modelo, portanto, n\u00e3o precisamos fornecer a fun\u00e7\u00e3o de resolu\u00e7\u00e3o. Somente para o campo <em>id<\/em>porque o couchbase retorna o valor no campo <strong>_id<\/strong>.<\/p>\n<h2>Consulta Graphql<\/h2>\n<p>A consulta \u00e9 a maneira pela qual recuperamos dados para o servidor.<\/p>\n<p>O objeto de consulta tamb\u00e9m \u00e9 um esquema, como os anteriores. Nesse caso, os campos s\u00e3o as consultas que permitimos que o usu\u00e1rio execute. Vamos definir tr\u00eas tipos de consulta.<\/p>\n<h3>Todos os lugares<\/h3>\n<p>Nessa consulta, vamos consultar todos os locais no banco de dados e vamos orden\u00e1-los pelo campo criado, para que retornemos primeiro os locais mais novos.<\/p>\n<p>Como vamos retornar uma matriz de Places, atribu\u00edmos a <strong>tipo<\/strong>\u00a0o tipo <em>GraphQLList<\/em>\u00a0e fornecemos o <em>Esquema de local<\/em><\/p>\n<p><code><br \/>\n...<\/code><\/p>\n<p>const PlaceSchema = require('.\/place');<\/p>\n<p>const Place = require('..\/models\/place');<\/p>\n<p>&#8230;<\/p>\n<p>allPlaces: {<\/p>\n<p>type: new GraphQLList(PlaceSchema),<\/p>\n<p>descri\u00e7\u00e3o: 'Query for all places',<\/p>\n<p>resolve(root, args) {<\/p>\n<p>return new Promise((resolve, reject) =&gt; {<\/p>\n<p>Place.find({}, {<\/p>\n<p>sort: {<\/p>\n<p>criado: -1<\/p>\n<p>},<\/p>\n<p>}, (err, places) =&gt; {<\/p>\n<p>se (err) {<\/p>\n<p>reject(err);<\/p>\n<p>}<\/p>\n<p>resolver(lugares);<\/p>\n<p>})<\/p>\n<p>});<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>Tamb\u00e9m adicionamos uma descri\u00e7\u00e3o, esse campo \u00e9 opcional.<\/p>\n<p>O \u00faltimo par\u00e2metro \u00e9 uma fun\u00e7\u00e3o, ou seja, a fun\u00e7\u00e3o resolve, que especificar\u00e1 como recuperaremos os dados do nosso banco de dados. Como nossas chamadas para o banco de dados s\u00e3o ass\u00edncronas, retornaremos uma promessa que usar\u00e1 o modelo Place que definimos com o ottoman. Com o modelo, usamos find para consultar os documentos e passamos como primeiro par\u00e2metro um objeto vazio, porque queremos consultar todos os documentos; o segundo par\u00e2metro s\u00e3o as op\u00e7\u00f5es da nossa consulta; nesse caso, vamos ordenar pelo campo <em>criado<\/em>\u00a0em ordem decrescente. Por fim, fornecemos a fun\u00e7\u00e3o de retorno de chamada que resolver\u00e1 a promessa com os valores ou a rejeitar\u00e1 em caso de erro.<\/p>\n<h3>Locais<\/h3>\n<p>Nessa consulta, vamos consultar usando a visualiza\u00e7\u00e3o Spatial, portanto, temos que passar os pontos bbox no par\u00e2metro da consulta.<\/p>\n<p><code><br \/>\n...<\/code><\/p>\n<p>const queryByLocation = require('..\/models\/place').queryByLocation;<\/p>\n<p>&#8230;<\/p>\n<p>Locais: {<\/p>\n<p>type: new GraphQLList(PlaceSchema),<\/p>\n<p>descri\u00e7\u00e3o: 'Query for all places inside the boundary box',<\/p>\n<p>args: {<\/p>\n<p>minLon: {<\/p>\n<p>type: new GraphQLNonNull(GraphQLFloat),<\/p>\n<p>description: 'Min Longitude of the boundary box' (Longitude m\u00ednima da caixa de limite),<\/p>\n<p>},<\/p>\n<p>maxLon: {<\/p>\n<p>type: new GraphQLNonNull(GraphQLFloat),<\/p>\n<p>descri\u00e7\u00e3o: \"Max Longitude of the boundary box\" (Longitude m\u00e1xima da caixa de limite),<\/p>\n<p>},<\/p>\n<p>minLat: {<\/p>\n<p>type: new GraphQLNonNull(GraphQLFloat),<\/p>\n<p>descri\u00e7\u00e3o: 'Latitude m\u00ednima da caixa de limite',<\/p>\n<p>},<\/p>\n<p>maxLat: {<\/p>\n<p>type: new GraphQLNonNull(GraphQLFloat),<\/p>\n<p>descri\u00e7\u00e3o: 'Latitude m\u00e1xima da caixa de limite',<\/p>\n<p>},<\/p>\n<p>},<\/p>\n<p>resolve(root, args) {<\/p>\n<p>\/\/ bbox = [ min Longitude , min Latitude , max Longitude , max Latitude ]<\/p>\n<p>const bbox = [<\/p>\n<p>args.minLon,<\/p>\n<p>args.minLat,<\/p>\n<p>args.maxLon,<\/p>\n<p>args.maxLat,<\/p>\n<p>];<\/p>\n<p>return new Promise((resolve, reject) =&gt; {<\/p>\n<p>queryByLocation(bbox, (err, places) =&gt; {<\/p>\n<p>se (err) {<\/p>\n<p>reject(err);<\/p>\n<p>}<\/p>\n<p>resolve(places.map((place) =&gt; place.value));<\/p>\n<p>})<\/p>\n<p>});<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>Primeiro, importamos a fun\u00e7\u00e3o que definimos para realizar a consulta espacial.<\/p>\n<p>Como na consulta anterior, definimos o tipo como uma matriz de locais e adicionamos uma descri\u00e7\u00e3o.<\/p>\n<p>Nessa consulta, precisamos de algum par\u00e2metro, ent\u00e3o definimos os args, que se referem ao par\u00e2metro; cada valor dentro de <em>argumentos<\/em>\u00a0correspondem aos par\u00e2metros; nesse caso, definimos 4, <strong>minLon, maxLon, minLat, maxLat<\/strong>\u00a0e, para todos eles, vamos definir o tipo como obrigat\u00f3rio e floats.<\/p>\n<p>Nesse caso, a fun\u00e7\u00e3o de resolu\u00e7\u00e3o tamb\u00e9m \u00e9 uma promessa. Primeiro, criamos a matriz bbox para passar a fun\u00e7\u00e3o <em>queryByLocation<\/em>. Em caso de erro, rejeitaremos a promessa com um erro; em caso de sucesso, precisaremos mapear o objeto do banco de dados, pois a visualiza\u00e7\u00e3o espacial retorna o ponto geogr\u00e1fico e o valor, e quando estivermos retornando o documento completo, isso mudar\u00e1 se definirmos uma visualiza\u00e7\u00e3o espacial diferente.<\/p>\n<h3>Local<\/h3>\n<p>A \u00faltima consulta que vamos definir \u00e9 a que consulta um local pelo seu ID.<\/p>\n<p><code><br \/>\nLocal: {<\/code><\/p>\n<p>Tipo: PlaceSchema,<\/p>\n<p>descri\u00e7\u00e3o: \"Consulta de um local pelo ID do local\",<\/p>\n<p>args: {<\/p>\n<p>id: {<\/p>\n<p>type: new GraphQLNonNull(GraphQLString),<\/p>\n<p>descri\u00e7\u00e3o: 'Place id',<\/p>\n<p>}<\/p>\n<p>},<\/p>\n<p>resolve(root, args) {<\/p>\n<p>return new Promise((resolve, reject) =&gt; {<\/p>\n<p>Place.getById(args.id, (err, place) =&gt; {<\/p>\n<p>se (err) {<\/p>\n<p>reject(err);<\/p>\n<p>}<\/p>\n<p>resolver(lugar);<\/p>\n<p>});<\/p>\n<p>});<\/p>\n<p>}<br \/>\nNesse caso, o tipo \u00e9 o <em>Esquema de local<\/em>nos args, s\u00f3 precisamos definir o <strong>id<\/strong>\u00a0e o definimos como string e obrigat\u00f3rio.<\/p>\n<p>A fun\u00e7\u00e3o resolve, mais uma vez, \u00e9 uma promessa; nesse caso, usaremos a fun\u00e7\u00e3o <em>queryById<\/em>\u00a0do modelo, e passamos o <em>id<\/em>\u00a0do objeto args.<\/p>\n<h2>Muta\u00e7\u00e3o do Graphql<\/h2>\n<p>Com as muta\u00e7\u00f5es, podemos modificar os dados em nosso servidor. Assim como a consulta, os objetos de muta\u00e7\u00e3o s\u00e3o esquemas. Portanto, temos que definir os mesmos campos que os esquemas anteriores.<\/p>\n<p>Quando realizamos a consulta de muta\u00e7\u00e3o, fornecemos os valores entre par\u00eanteses e, assim como as consultas, fornecemos os valores que queremos recuperar do objeto modificado.<\/p>\n<p>Aqui, realizaremos a cria\u00e7\u00e3o, a atualiza\u00e7\u00e3o e a exclus\u00e3o de Locais.<\/p>\n<h3>createPlace<\/h3>\n<p>Nesta muta\u00e7\u00e3o, vamos criar um novo local.<\/p>\n<p>No tipo do esquema, vamos defini-lo como <em>Esquema de local<\/em>porque vamos retornar o local criado.<\/p>\n<p><code><br \/>\ncreatePlace: {<\/code><\/p>\n<p>Tipo: PlaceSchema,<\/p>\n<p>descri\u00e7\u00e3o: 'Create a place',<\/p>\n<p>args: {<\/p>\n<p>nome: {<\/p>\n<p>type: new GraphQLNonNull(GraphQLString),<\/p>\n<p>description: 'Nome do local',<\/p>\n<p>},<\/p>\n<p>descri\u00e7\u00e3o: {<\/p>\n<p>type: new GraphQLNonNull(GraphQLString),<\/p>\n<p>description: \"Descri\u00e7\u00e3o do local\",<\/p>\n<p>},<\/p>\n<p>latitude: {<\/p>\n<p>type: new GraphQLNonNull(GraphQLFloat),<\/p>\n<p>description: 'Latitude do local',<\/p>\n<p>},<\/p>\n<p>longitude: {<\/p>\n<p>type: new GraphQLNonNull(GraphQLFloat),<\/p>\n<p>description: 'Longitude do local',<\/p>\n<p>}<\/p>\n<p>},<\/p>\n<p>resolve(source, args) {<\/p>\n<p>return new Promise((resolve, reject) =&gt; {<\/p>\n<p>const place = new Place({<\/p>\n<p>name: args.name,<\/p>\n<p>description: args.description,<\/p>\n<p>localiza\u00e7\u00e3o: {<\/p>\n<p>lat: args.latitude,<\/p>\n<p>lon: args.longitude,<\/p>\n<p>},<\/p>\n<p>});<\/p>\n<p>place.save((err) =&gt; {<\/p>\n<p>se (err) {<\/p>\n<p>reject(err);<\/p>\n<p>}<\/p>\n<p>resolver(lugar);<\/p>\n<p>})<\/p>\n<p>});<\/p>\n<p>}<\/p>\n<p>}<br \/>\nComo nas consultas, definimos os argumentos com os valores necess\u00e1rios para criar um novo local. Nesse caso, exigimos que o nome e a descri\u00e7\u00e3o sejam strings e que a latitude e a longitude sejam floats; todos os campos ser\u00e3o obrigat\u00f3rios.<\/p>\n<p>Na fun\u00e7\u00e3o resolver, vamos retornar uma promessa. Dentro da promessa, vamos criar o local com os valores da consulta dentro de <em>argumentos<\/em>. Em seguida, vamos realizar <em>salvar<\/em>\u00a0no objeto do local. Por fim, no caso de um erro ao salvar o local, rejeitaremos a promessa com o erro ou resolveremos a promessa com os dados do local.<\/p>\n<h3>updatePlace<\/h3>\n<p>Como no <em>createPlace<\/em>\u00a0muta\u00e7\u00e3o, o <em>updatePlace<\/em>\u00a0A muta\u00e7\u00e3o \u00e9 semelhante, as diferen\u00e7as s\u00e3o que, nesse caso, todos os valores nos args n\u00e3o s\u00e3o obrigat\u00f3rios e o campo id \u00e9 uma string obrigat\u00f3ria; e na fun\u00e7\u00e3o resolve, primeiro vamos procurar o objeto pelo par\u00e2metro <em>id<\/em>Em seguida, verificamos os campos fornecidos pelo usu\u00e1rio e atualizamos o local e, por fim, salvamos e retornamos o novo objeto<\/p>\n<p><code><br \/>\nupdatePlace: {<\/code><\/p>\n<p>Tipo: PlaceSchema,<\/p>\n<p>descri\u00e7\u00e3o: \"Atualizar um local\",<\/p>\n<p>args: {<\/p>\n<p>id: {<\/p>\n<p>type: new GraphQLNonNull(GraphQLString),<\/p>\n<p>descri\u00e7\u00e3o: 'Id do local',<\/p>\n<p>},<\/p>\n<p>nome: {<\/p>\n<p>Tipo: GraphQLString,<\/p>\n<p>description: 'Nome do local',<\/p>\n<p>},<\/p>\n<p>descri\u00e7\u00e3o: {<\/p>\n<p>Tipo: GraphQLString,<\/p>\n<p>description: \"Descri\u00e7\u00e3o do local\",<\/p>\n<p>},<\/p>\n<p>latitude: {<\/p>\n<p>Tipo: GraphQLFloat,<\/p>\n<p>description: 'Latitude do local',<\/p>\n<p>},<\/p>\n<p>longitude: {<\/p>\n<p>Tipo: GraphQLFloat,<\/p>\n<p>description: 'Longitude do local',<\/p>\n<p>}<\/p>\n<p>},<\/p>\n<p>resolve(source, args) {<\/p>\n<p>return new Promise((resolve, reject) =&gt; {<\/p>\n<p>Place.getById(args.id, (err, place) =&gt; {<\/p>\n<p>se (err) {<\/p>\n<p>reject(err);<\/p>\n<p>} else {<\/p>\n<p>Se (args.name) {<\/p>\n<p>place.name = args.name;<\/p>\n<p>}<\/p>\n<p>Se (args.description) {<\/p>\n<p>place.name = args.name;<\/p>\n<p>}<\/p>\n<p>Se (args.latitude) {<\/p>\n<p>place.location.lat = args.latitude;<\/p>\n<p>}<\/p>\n<p>Se (args.longitude) {<\/p>\n<p>place.location.lon = args.longitude;<\/p>\n<p>}<\/p>\n<p>place.save((err) =&gt; {<\/p>\n<p>se (err) {<\/p>\n<p>reject(err);<\/p>\n<p>}<\/p>\n<p>resolver(lugar);<\/p>\n<p>});<\/p>\n<p>}<\/p>\n<p>})<\/p>\n<p>});<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<h3>deletePlace<\/h3>\n<p>A \u00faltima muta\u00e7\u00e3o \u00e9 a exclus\u00e3o, na qual definimos um tipo de <em>Esquema de local<\/em>porque vamos retornar o objeto que exclu\u00edmos.<\/p>\n<p>Nos args, s\u00f3 precisamos definir o <em>id<\/em>\u00a0do local a ser exclu\u00eddo.<\/p>\n<p>Na fun\u00e7\u00e3o de resolu\u00e7\u00e3o, retornaremos uma Promise que procurar\u00e1 o local pelo ID e executar\u00e1 a remo\u00e7\u00e3o. Rejeitaremos a promessa caso o local n\u00e3o seja encontrado ou se houver um erro ao remov\u00ea-lo; ou resolveremos a promessa com os dados do local caso o removamos com \u00eaxito.<\/p>\n<p><code><br \/>\ndeletePlace: {<\/code><\/p>\n<p>Tipo: PlaceSchema,<\/p>\n<p>descri\u00e7\u00e3o: 'Delete a place',<\/p>\n<p>args: {<\/p>\n<p>id: {<\/p>\n<p>type: new GraphQLNonNull(GraphQLString),<\/p>\n<p>descri\u00e7\u00e3o: 'Id do local',<\/p>\n<p>},<\/p>\n<p>},<\/p>\n<p>resolve(source, args) {<\/p>\n<p>return new Promise((resolve, reject) =&gt; {<\/p>\n<p>Place.getById(args.id, (err, place) =&gt; {<\/p>\n<p>se (err) {<\/p>\n<p>reject(err);<\/p>\n<p>} else {<\/p>\n<p>place.remove((err) =&gt; {<\/p>\n<p>se (err) {<\/p>\n<p>reject(err);<\/p>\n<p>}<\/p>\n<p>resolver(lugar);<\/p>\n<p>});<\/p>\n<p>}<\/p>\n<p>})<\/p>\n<p>});<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<h2>Teste<\/h2>\n<p>Para testar nosso aplicativo, vamos usar o Graphiql, que permitimos em nosso servidor. Para isso, precisamos acessar https:\/\/localhost:5000\/graphql<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/graphiql.png\" alt=\"graphiql\" \/><\/p>\n<p>Nessa p\u00e1gina, podemos realizar as consultas e muta\u00e7\u00f5es que definimos anteriormente.<\/p>\n<h3>Criar<\/h3>\n<p><code><br \/>\nmuta\u00e7\u00e3o {<\/code><\/p>\n<p>createPlace(<\/p>\n<p>nome: \"testplace\"<\/p>\n<p>descri\u00e7\u00e3o: \"testdescription\"<\/p>\n<p>latitude: 1,36<\/p>\n<p>longitude: 18,36<\/p>\n<p>)\u00a0{<\/p>\n<p>id<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/mutation_create.png\" alt=\"mutation create\" \/><\/p>\n<h3>Atualiza\u00e7\u00e3o<\/h3>\n<p><code><br \/>\nmuta\u00e7\u00e3o {<\/code><\/p>\n<p>updatePlace(<\/p>\n<p>id: \u201c41133f98-18e8-4979-89e0-7af012b0e14f\u201d<\/p>\n<p>nome: \"updateplace\"<\/p>\n<p>descri\u00e7\u00e3o: \"updatedescription\"<\/p>\n<p>latitude: 2,36<\/p>\n<p>longitude: 15,96<\/p>\n<p>)\u00a0{<\/p>\n<p>id<\/p>\n<p>nome<\/p>\n<p>descri\u00e7\u00e3o<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/mutation_update.png\" alt=\"mutation update\" \/><\/p>\n<h3>Excluir<\/h3>\n<p><code><br \/>\nmuta\u00e7\u00e3o {<\/code><\/p>\n<p>deletePlace(id: \"41133f98-18e8-4979-89e0-7af012b0e14f\") {<\/p>\n<p>id<\/p>\n<p>}<\/p>\n<p>}<br \/>\n<img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/mutation_delete.png\" alt=\"mutation delete\" \/><\/p>\n<h3>Consultar tudo<\/h3>\n<p><code><br \/>\nconsulta {<\/code><\/p>\n<p>allPlaces {<\/p>\n<p>id<\/p>\n<p>nome<\/p>\n<p>localiza\u00e7\u00e3o {<\/p>\n<p>lat<\/p>\n<p>solit\u00e1rio<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/query_all.png\" alt=\"query all\" \/><\/p>\n<h3>Consulta por caixa de limite<\/h3>\n<p><code><br \/>\nconsulta {<\/code><\/p>\n<p>Locais(<\/p>\n<p>minLon: 3<\/p>\n<p>maxLon: 5<\/p>\n<p>minLat: 49<\/p>\n<p>maxLat: 51<\/p>\n<p>)\u00a0{<\/p>\n<p>nome<\/p>\n<p>localiza\u00e7\u00e3o {<\/p>\n<p>lat<\/p>\n<p>solit\u00e1rio<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>}<br \/>\n<img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/query_bbox.png\" alt=\"query bbox\" \/><\/p>\n<h3>Consultar um local por id<\/h3>\n<p><code><br \/>\n```<\/code><\/p>\n<p>muta\u00e7\u00e3o {<\/p>\n<p>deletePlace(id: \"41133f98-18e8-4979-89e0-7af012b0e14f\") {<\/p>\n<p>id<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&#8220;`<br \/>\n<img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/query_id.png\" alt=\"query id\" \/><\/p>\n<h2>Conclus\u00e3o<\/h2>\n<p>O Graphql \u00e9 uma boa linguagem de consulta que nos permite consultar apenas as informa\u00e7\u00f5es que definimos, de modo que podemos evitar a busca excessiva ou insuficiente e podemos ter certeza de que sempre teremos os dados.<\/p>\n<p>Em um servidor Graphql, os clientes usam apenas um \u00fanico ponto de extremidade, o que oculta a complexidade e a l\u00f3gica do back-end, de modo que o servidor pode se conectar a diferentes back-ends ou usar diferentes bancos de dados e, se eles mudarem, a l\u00f3gica dos clientes n\u00e3o precisar\u00e1 mudar porque o ponto de extremidade \u00e9 o mesmo.<\/p>\n<p>Tamb\u00e9m vimos como realizar uma consulta geogr\u00e1fica em nossos dados com o couchbase.<\/p>\n<h2>Refer\u00eancias<\/h2>\n<ul>\n<li><u><a href=\"https:\/\/github.com\/jmn8718\/node-couchbase-graphql.git\" target=\"_blank\" rel=\"noopener noreferrer\">C\u00f3digo<\/a><\/u><\/li>\n<li><u><a href=\"https:\/\/graphql.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">Graphql<\/a><\/u><\/li>\n<li><u><a href=\"https:\/\/developer.github.com\/early-access\/graphql\/\" target=\"_blank\" rel=\"noopener noreferrer\">Github graphql<\/a><\/u><\/li>\n<li><u><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/4.6\/views\/sv-writing-views.html\" target=\"_blank\" rel=\"noopener noreferrer\">Visualiza\u00e7\u00e3o espacial do Couchbase<\/a><\/u><\/li>\n<li><u><a href=\"https:\/\/wiki.openstreetmap.org\/wiki\/Bounding_Box\" target=\"_blank\" rel=\"noopener noreferrer\">Caixa de limite<\/a><\/u><\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p> Graphql \u00e9 uma linguagem de consulta para APIs, foi desenvolvida pelo Facebook e lan\u00e7ada em 2015. Ela foi projetada para criar aplicativos de clientes, fornecendo uma sintaxe e um sistema intuitivos e flex\u00edveis para descrever seus requisitos de dados e intera\u00e7\u00f5es. O<\/p>","protected":false},"author":53,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1822,10128],"tags":[1726],"ppma_author":[9026],"class_list":["post-2854","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-node-js","category-ottoman","tag-graph-database"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.4 (Yoast SEO v26.4) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Graphql server in nodejs with express - The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"Learn how to perform a geographical query in our data with couchbase.and how we can avoid underfetching or overfetching using Graphql.\" \/>\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\/pt\/graphql-server-node-couchbase-ottoman-spatial-view\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Graphql server with node and couchbase, ottoman and spatial view\" \/>\n<meta property=\"og:description\" content=\"Learn how to perform a geographical query in our data with couchbase.and how we can avoid underfetching or overfetching using Graphql.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/pt\/graphql-server-node-couchbase-ottoman-spatial-view\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2017-02-28T16:41:20+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T04:40:21+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/create_view.png\" \/>\n<meta name=\"author\" content=\"Laura Czajkowski, Developer Community Manager, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Laura Czajkowski, Developer Community Manager, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/\"},\"author\":{\"name\":\"Laura Czajkowski, Developer Community Manager, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5f1a0ece4e644bc8c037686fbc8f3220\"},\"headline\":\"Graphql server with node and couchbase, ottoman and spatial view\",\"datePublished\":\"2017-02-28T16:41:20+00:00\",\"dateModified\":\"2025-06-14T04:40:21+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/\"},\"wordCount\":2619,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"graph database\"],\"articleSection\":[\"Node.js\",\"Ottoman.js ODM\"],\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/\",\"name\":\"Graphql server in nodejs with express - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2017-02-28T16:41:20+00:00\",\"dateModified\":\"2025-06-14T04:40:21+00:00\",\"description\":\"Learn how to perform a geographical query in our data with couchbase.and how we can avoid underfetching or overfetching using Graphql.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Graphql server with node and couchbase, ottoman and spatial view\"}]},{\"@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\":\"pt-BR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@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\/5f1a0ece4e644bc8c037686fbc8f3220\",\"name\":\"Laura Czajkowski, Developer Community Manager, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/9deb07d5daaa00220534c31768bc4409\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g\",\"caption\":\"Laura Czajkowski, Developer Community Manager, Couchbase\"},\"description\":\"Laura Czajkowski is the Snr. Developer Community Manager at Couchbase overseeing the community. She\u2019s responsible for our monthly developer newsletter.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/pt\/author\/laura-czajkowski\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Graphql server in nodejs with express - The Couchbase Blog","description":"Saiba como realizar uma consulta geogr\u00e1fica em nossos dados com o couchbase e como podemos evitar a busca insuficiente ou excessiva usando o Graphql.","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\/pt\/graphql-server-node-couchbase-ottoman-spatial-view\/","og_locale":"pt_BR","og_type":"article","og_title":"Graphql server with node and couchbase, ottoman and spatial view","og_description":"Learn how to perform a geographical query in our data with couchbase.and how we can avoid underfetching or overfetching using Graphql.","og_url":"https:\/\/www.couchbase.com\/blog\/pt\/graphql-server-node-couchbase-ottoman-spatial-view\/","og_site_name":"The Couchbase Blog","article_published_time":"2017-02-28T16:41:20+00:00","article_modified_time":"2025-06-14T04:40:21+00:00","og_image":[{"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/02\/create_view.png","type":"","width":"","height":""}],"author":"Laura Czajkowski, Developer Community Manager, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Laura Czajkowski, Developer Community Manager, Couchbase","Est. reading time":"14 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/"},"author":{"name":"Laura Czajkowski, Developer Community Manager, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5f1a0ece4e644bc8c037686fbc8f3220"},"headline":"Graphql server with node and couchbase, ottoman and spatial view","datePublished":"2017-02-28T16:41:20+00:00","dateModified":"2025-06-14T04:40:21+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/"},"wordCount":2619,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["graph database"],"articleSection":["Node.js","Ottoman.js ODM"],"inLanguage":"pt-BR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/","url":"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/","name":"Graphql server in nodejs with express - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2017-02-28T16:41:20+00:00","dateModified":"2025-06-14T04:40:21+00:00","description":"Saiba como realizar uma consulta geogr\u00e1fica em nossos dados com o couchbase e como podemos evitar a busca insuficiente ou excessiva usando o Graphql.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/graphql-server-node-couchbase-ottoman-spatial-view\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Graphql server with node and couchbase, ottoman and spatial view"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"Blog do Couchbase","description":"Couchbase, o banco de dados 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":"pt-BR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"Blog do Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"pt-BR","@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\/5f1a0ece4e644bc8c037686fbc8f3220","name":"Laura Czajkowski, gerente da comunidade de desenvolvedores, Couchbase","image":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/9deb07d5daaa00220534c31768bc4409","url":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","caption":"Laura Czajkowski, Developer Community Manager, Couchbase"},"description":"Laura Czajkowski \u00e9 a Snr. Developer Community Manager da Couchbase, supervisionando a comunidade. Ela \u00e9 respons\u00e1vel pelo nosso boletim informativo mensal para desenvolvedores.","url":"https:\/\/www.couchbase.com\/blog\/pt\/author\/laura-czajkowski\/"}]}},"authors":[{"term_id":9026,"user_id":53,"is_guest":0,"slug":"laura-czajkowski","display_name":"Laura Czajkowski, Developer Community Manager, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","author_category":"","last_name":"Czajkowski","first_name":"Laura","job_title":"","user_url":"","description":"Laura Czajkowski \u00e9 a Snr. Developer Community Manager da Couchbase, supervisionando a comunidade. Ela \u00e9 respons\u00e1vel pelo nosso boletim informativo mensal para desenvolvedores."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/2854","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/users\/53"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=2854"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/2854\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=2854"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=2854"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=2854"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/ppma_author?post=2854"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}