MongoDB REST API
Tags: mongodb, nosql, webapi
Published: 2019-06-01 04:13:15

---
title: MongoDB REST API
published: true
description: Um breve passeio sobre uma interface HTTP para MongoDB
tags: mongodb, nosql, webapi
---

Fala pessoALL, estou contente com a repercussão do meu último artigo onde iniciei uma série sobre o MongoDB Connector for BI. Os feedbacks têm sido muito bons e logo mais chega o segundo post. Porém, alguns questionamentos sugiram sobre a que o BI Connector não seria a única forma de se conectar uma instância MongoDB e ferramentas de BI, mas porque? Porque existem as REST APIs! Então vamos lá...

###Deixando às claras

Antes de falar sobre uma dessas alternativas temos que entender alguns pontos e diferenças entre o BI Connector e as REST APIs.

A mais importante é que o BI Connector, assim como o driver OBDC para MongoDB são desenvolvidos seguindo os padrões e melhores formas de acesso a dados. Existem formas e formas de se acessar dados e se desenvolver drivers, logo o BI Connector e o ODBC Driver utilizam esses padrões pra entregar os dados de forma muito mais performática do que as REST APIs disponíveis. Mas então porque elas existem?

Existem para facilitar a vida de desenvolvedores oferecendo uma forma rápida de disponibilizar o acesso e troca de dados entre aplicações, aliás esse é o principal objetivo: troca de dados entre aplicações! Através dessas APIs é possível utilizar os métodos HTTP para fazer requisições no MongoDB e a maioria delas provê recursos que vão desde um simples CRUD quanto a comandos de administração de clusters!

Mas Leandro, já que o objetivo principal é a troca de dados entre aplicações, minha ferramenta de BI não se enquadra aí? Sim! Mas não é a melhor forma cara! Enquanto uma REST API disponibiliza um retorno em JSON a ser tratado 100% pela sua ferramenta, os drivers oferecem uma interação muito melhor com opções de queries mais avançadas. Portanto, se quer integrar com uma ferramenta de BI, utilize a forma correta! Se quiser ter um spoiler de uma outra forma, vá até o final do artigo, porque agora vou apresentar uma REST API muito bacana construída em Python... aliás, Python é vida e melhor que R! hahahahaha

###Eve RESTful

[Eve](https://docs.mongodb.com/ecosystem/tools/http-interfaces/#rest-interfaces) é uma REST API escrita em Python, tem vários métodos disponíveis e é compatível com Python 2.6, 2.7, 3.3 e 3.6.

####O básico

Bom, depois de conhecer a história da Eve vamos ver como faremos para utilizá-la. Esse tutorial você pode encontrar diretamente na documentação, mas aqui vou fazer algumas observações.

A instalação do Eve é super simples: pip3 install eve (revisar isso)



Crie um arquivo chamado run.py e copie o seguinte conteúdo:

```python
from eve import Eve
app = Eve()
if __name__ == '__main__':
    app.run()
```

Agora crie outro arquivo chamado settings.py, deixando no mesmo diretório do arquivo run.py. Esse é um arquivo de configurações que segue o padrão de um módulo Python e vai dizer para Eve que sua API só acessa um recurso: people.

```python
DOMAIN = { ‘people’: {}}
```


Agora é só executar sua API:
```bash
python3 run.py
```

E para consumir:
```bash
curl -i http://127.0.0.1:5000
```

Feito, você já tem uma requisição GET e a resposta é parecida com essa:

Por default sua API é somente read-only, execute uma requisição de DELETE por exemplo e veja a resposta:
```bash
curl -X DELETE http://127.0.0.1:5000/people
```

####Conectando com o MongoDB

No arquivo settings.py, adicione as seguintes linhas:
```python
MONGO_HOST = ‘localhost’
MONGO_PORT = 27017

# Se você não tem autenticação habilitada na sua instância, ignore o bloco abaixo (mas é altamente recomendável o uso de autenticação)
MONGO_USERNAME = ‘<seu_usuario>’
MONGO_PASSWORD = ‘<sua_senha>’
#Nome do seu database de autenticação
MONGO_AUTH_SOURCE = ‘<dbname>’

#Nome do banco de dados onde você quer se conectar
MONGO_DBNAME = ‘<nome_do_database>’
```


Seguindo os princípios de laziness do MongoDB, você não precisa criar “formalmente” um database ou uma collection. Se você requisitar um GET num database vazio ou não existente você terá uma resposta 200 OK, outros métodos como DELETE/PATCH/PUT receberão 404 Not Found, já um POST fará a criação do database e da collection de acordo com o contexto.

Como disse, por default sua API é read-only, então vamos habilitar todos os métodos para um CRUD:

```python
RESOURCE_METHODS = [‘GET’, ‘POST’, ‘DELETE’]
ITEM_METHODS = [‘GET’, ‘PATCH’, ‘PUT’, ‘DELETE’]
```

Os RESOURCE_METHODS equivale a todos os métodos que quero deixar exposto para os endpoints (/people), já o ITEM_METHODS equivale aos endpoints e itens (/people/<ObjectId>). Essas duas configurações tem escopo global e se aplicam a todos os endpoints, mas podemos habilitar ou desabilitar métodos HTTP individualmente no nível de um endpoint.

Depois de liberarmos os métodos, podemos também criar um schema para o nosso recurso people. Adicione essas linhas ao arquivo settings.py:

```python
schema = {
    # baseado no Cerberus grammar. Dê uma olhada no Cerberus project
    # (https://github.com/pyeve/cerberus) pra maiores detalhes.
    'firstname': {
        'type': 'string',
        'minlength': 1,
        'maxlength': 10,
    },
    'lastname': {
        'type': 'string',
        'minlength': 1,
        'maxlength': 15,
        'required': True,
        'unique': True,
    },
    'role': {
        'type': 'list',
        'allowed': ["author", "contributor", "copy"],
    },
    'location': {
        'type': 'dict',
        'schema': {
            'address': {'type': 'string'},
            'city': {'type': 'string'}
        },
    },
    'born': {
        'type': 'datetime',
    },
}
```

Mais detalhes sobre schema validation [aqui](https://docs.python-eve.org/en/stable/validation.html#validation).

Vamos agora customizar o acesso ao endpoint people:
* Trocar o nome do item para person
* Adicionar um endpoint customizado em /people/<lastname>
* Fazer um override nas diretivas de controle de cache
* Desabilitar o método DELETE para o endpoint /people (deixaremos habilitado para os outros endpoints futuros)

Adicione mais essas linhas ao arquivo settings.py:

```python
people = {
   'item_title': 'person',
    'additional_lookup': {
        'url': 'regex("[\w]+")',
        'field': 'lastname'
    },
    'cache_control': 'max-age=10,must-revalidate',
    'cache_expires': 10,
    'resource_methods': ['GET', 'POST'],
    'schema': schema
}
```

E finalmente e ainda no settings.py, faremos a atualização do domínio people:

```python
DOMAIN = {
  'people': people,
}
```

Salve as alterações e execute novamente o run.py. E vamos inserir alguns documentos no endpoint people.


Depois de inserir, podemos dar um GET e recuperar os documentos através do endpoint /people/lastname:

```bash
$ curl -d '[{"firstname": "barack", "lastname": "obama"}, {"firstname": "mitt", "lastname": "romney"}]' -H 'Content-Type: application/json'  http://127.0.0.1:5000/people
```


Legal né? Rapidamente e com poucas linhas de código podemos expor os dados através de uma REST API. Obviamente, recursos mais avançados de segurança devem ser observados e configurados, mas voltando ao ponto inicial do artigo: essa é uma maneira de facilitar a vida de desenvolvedores que precisam trocar dados de forma rápida e simples!


###Mas e o spoiler que você prometeu?

Sim... já ia me esquecendo! Uma ferramenta muito interessante também faz mais do que uma ponte entre um cluster MongoDB e sua ferramenta de BI: o [Dremio](https://www.dremio.com/)! Como é apenas um spoiler, não vou entrar em detalhes aqui, mas garanto que é uma ferramenta muito legal e com vários recursos e também possui integração nativa com os principais players de mercado de BI. Aguardem que assim que terminar nossa série sobre o BI Connector escreverei sobre ele!

Até mais! ;)