Fala pessoal, tudo bem? Hoje vamos ver como fazer para pegar dados do MongoDB e levá-los para o SQL Server através de uma simples REST API em NodeJS.
Desde a versão 2016 o SQL Server tem suporte a JSON (JSON é vida!), isso ampliou suas formas de comunicação com aplicações e outros bancos de dados, como por exemplo o MongoDB. Mesmo sendo possível a comunicação com o MongoDB através de ODBC, uma API REST deixa essa comunicação mais fluida, porque uma vez publicada, o SQL Server se conecta a ela e os dados chegam de forma padronizada.
O intuito desse artigo é demonstrar de forma simples a construção de uma API que se conecta ao MongoDB e fazer com que o SQL Server faça requests a ela para obter os dados. Não vou abordar detalhes sobre a construção da API, o foco é a comunicação entre os dois bancos.
Este artigo é baseado num post da equipe do Studio 3T e pode ser encontrado nesse link.
Limitações e pré-requisitos
Durante os testes para fazer esse post, testei alguns cenários e encontrei algumas limitações:
- Por requerer parâmetros de configurações, digamos mais administrativas, não é possível utilizar o Azure SQL Databases;
- Bem como o SQL Server for Linux, por conta de algumas DLLs, que obviamente estão disponíveis somente para Windows;
Utilizei a versão SQL Server 2017 Developer com Windows Server 2016 na Azure.
Você também precisará do NodeJS e de alguns módulos que podem ser instalados através do NPM.
Do lado do MongoDB, criei uma instância M0 no MongoDB Atlas que é free também na Azure. Se você não conhece o MongoDB Atlas, recomendo a leitura deste artigo que escrevi sobre ele!
O Dataset
Como exemplo, baixei do Kaggle um dataset pequeno sobre carros (download aqui), utilizei apenas alguns campos e nosso documento no MongoDB ficou assim:
{
_id: ObjectId(5c6ef4d6aaeaf27b7cdb76d4),
brand: "alfa-romero",
fuelType: "gas",
numOfDoors: "two",
bodyStyle: "convertible",
engineLocation: "front",
numberOfCylinders: "four",
horsepower: 111
}A API
Novamente, o foco não é uma API perfeita, logo, o código abaixo pode (e deve) ser muito melhorado, mas para efeitos de estudo ela nos atende bem:
const express = require("express"),
app = express(),
bodyParser = require("body-parser"),
cors = require("cors"),
MongoClient = require('mongodb').MongoClient;
const port = 8000;
var mongodbURI = "mongodb+srv://user:pass@seu_servidor_mongodb/test?retryWrites=true"
app.use(cors())
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
MongoClient.connect(mongodbURI, {useNewUrlParser: true}, function(err, client){
if(err) throw err;
app.get('/', function(req, res){
res.json({
"message": "Welcome to Cars Sample API",
"Find Brand Name": "curl -X GET http://server.com/brand/",
})
});
app.get('/brand/:name', function(req, res){
const collection = client.db('newCars').collection('cars');
collection
.find({
brand: {
$regex: '\\N*' + req.params.name + '\\N*',
$options: "si"
}
})
.project({
_id: 0
})
.sort({
brand: 1
})
.toArray(function(err, result){
if(err) throw err;
res.setHeader("Content-Type", "application/json");
res.json({
result
});
})
});
})
app.listen(port, () => {
console.log(`listening on port ${port}`)
})Note que temos dois pontos de entrada em nossa API:
- O / apenas nos exibe uma mensagem de boas vindas
- O /brand/:name recebe o nome da marca de automóveis que queremos listar, esse é o parâmetro de entrada para nossa consulta no MongoDB. Note também que utilizei uma busca utilizando o $regex para possibilitar uma busca mais abrangente, sem nos preocuparmos de que forma o nome da marca está sendo inputado. O retorno é um array de documentos:

Fazendo a mágica no SQL Server
Agora, que temos nossa API retornando os dados corretamente, vamos para o SQL Server e fazer os requests a partir dele. Vamos utilizar ‘Ole Automation Procedures’ que por default e para dificultar um ataque por SQL Injection está desabilitado. Para habilitar utilizei os seguintes comandos:
sp_configure 'show advanced options', 1; GO RECONFIGURE; GO sp_configure 'Ole Automation Procedures', 1; GO RECONFIGURE; GO
Agora, vamos criar uma procedure para executar serviços REST no SQL Server. Esse código é todo do artigo original e não precisei fazer nenhuma modificação:
GO
IF Object_Id('dbo.GetWebService','P') IS NOT NULL
DROP procedure dbo.GetWebService
GO
CREATE PROCEDURE dbo.GetWebService
@TheURL VARCHAR(255),-- the url of the web service
@TheResponse NVARCHAR(4000) OUTPUT --the resulting JSON
AS
BEGIN
DECLARE @obj INT, @hr INT, @status INT, @message VARCHAR(255);
/**
Summary: >
This is intended for using web services that
utilize JavaScript Object Notation (JSON). You pass it the link to
a webservice and it returns the JSON string
Note: >
OLE Automation objects can be used within a Transact-SQL batch, but
SQL Server blocks access to OLE Automation stored procedures because
this component is turned off as part of the security configuration.
Author: PhilFactor
Date: 26/10/2017
Database: PhilFactor
Examples:
- >
DECLARE @response NVARCHAR(MAX)
EXECUTE dbo.GetWebService 'http://headers.jsontest.com/', @response OUTPUT
SELECT @response
Returns: >
nothing
**/
EXEC @hr = sp_OACreate 'MSXML2.ServerXMLHttp', @obj OUT;
SET @message = 'sp_OAMethod Open failed';
IF @hr = 0 EXEC @hr = sp_OAMethod @obj, 'open', NULL, 'GET', @TheURL, false;
SET @message = 'sp_OAMethod setRequestHeader failed';
IF @hr = 0
EXEC @hr = sp_OAMethod @obj, 'setRequestHeader', NULL, 'Content-Type',
'application/x-www-form-urlencoded';
SET @message = 'sp_OAMethod Send failed';
IF @hr = 0 EXEC @hr = sp_OAMethod @obj, send, NULL, '';
SET @message = 'sp_OAMethod read status failed';
IF @hr = 0 EXEC @hr = sp_OAGetProperty @obj, 'status', @status OUT;
IF @status <> 200 BEGIN
SELECT @message = 'sp_OAMethod http status ' + Str(@status), @hr = -1;
END;
SET @message = 'sp_OAMethod read response failed';
IF @hr = 0
BEGIN
EXEC @hr = sp_OAGetProperty @obj, 'responseText', @Theresponse OUT;
END;
EXEC sp_OADestroy @obj;
IF @hr <> 0 RAISERROR(@message, 16, 1);
END;Criamos então uma procedure chamada GetWebService que recebe como parâmetro de entrada uma URL e como resultado o JSON retornado.
Executamos da seguinte maneira, somente alterando a URL para o seu servidor:
E temos como resultado os dados tabulados, prontos para serem persistidos no SQL Server:

Legal, né? O exemplo é simples, mas pode ser facilmente modificado e gerar uma variedade de possibilidades para a comunicação entre o MongoDB e o SQL Server. Um exemplo é que em determinados cenários podemos eliminar ETLs para inserir dados no SQL Server a partir do MongoDB. Por outro lado vemos também uma maior abertura por parte do SQL Server utilizando JSON e isso é muito bacana!
Bem, espero que tenham gostado. Deixe seu like e compartilhe à vontade!
Ah! Se você quiser saber mais sobre MongoDB, dê uma olhada nas próximas turmas de treinamento, serão online e ao vivo, presenciais em São Paulo e Brasília!
Até a próxima!
