Using JOINs in MongoDB NoSQL Databases

 Using $lookUp with NoSQL

Thanks to Julian Motz for gently helping to peer review this article.

uma das maiores diferenças entre as bases de dados SQL e NoSQL é a JOIN. Em bases de dados relacionais, a cláusula de junção SQL permite combinar linhas de duas ou mais tabelas usando um campo comum entre elas. Por exemplo, se você tem tabelas de books e publishers, você pode escrever comandos SQL como:

SELECT book.title, publisher.nameFROM bookLEFT JOIN book.publisher_id ON publisher.id;

por outras palavras, a tabela book tem um campo publisher_id que faz referência ao campo id na tabela publisher. Isto é prático, uma vez que um único editor poderia oferecer milhares de livros. Se alguma vez precisarmos atualizar os detalhes de um editor, podemos mudar um único registro. A redundância de dados é minimizada, uma vez que não precisamos repetir a informação do editor para cada livro. A técnica é conhecida como normalização.As bases de dados SQL oferecem uma série de características de Normalização e restrição para garantir a manutenção das relações.

NoSQL = no JOIN?

nem sempre …

bases de dados orientadas para documentos, tais como o MongoDB, são concebidas para armazenar dados desnormalizados. Idealmente, não deve haver nenhuma relação entre as coleções. Se forem exigidos os mesmos dados em dois ou mais documentos, estes devem ser repetidos.Isto pode ser frustrante, uma vez que há poucas situações em que você nunca precisa de dados relacionais. Felizmente, o MongoDB 3.2 introduz um novo operador $lookup que pode realizar uma operação de união à esquerda em duas ou mais coleções. Mas há uma captura …

a agregação MongoDB

$lookup só é permitida em operações de agregação. Pense nisto como um pipeline de operadores que consultam, filtram e agrupam um resultado. A saída de um operador é usada como a entrada para o próximo.

a agregação é mais difícil de compreender do que as consultas mais simples find e irá geralmente correr mais lentamente. No entanto, eles são poderosos e uma opção inestimável para operações de busca complexas.A agregação é melhor explicada com um exemplo. Presumimos que estamos a criar uma plataforma de redes sociais com uma colecção user. Armazena os detalhes de cada usuário em documentos separados. Por exemplo:

{ "_id": ObjectID("45b83bda421238c76f5c1969"), "name": "User One", "email: "[email protected]", "country": "UK", "dob": ISODate("1999-09-13T00:00:00.000Z")}

podemos adicionar tantos campos quanto necessário, mas todos os documentos MongoDB exigem um campo _id que tem um valor único. A _id é semelhante a uma chave primária SQL, e será inserida automaticamente se necessário.

nossa rede social agora requer uma coleção post, que armazena inúmeras atualizações perspicazes dos usuários. Os documentos armazenam o texto, a data, uma classificação e uma referência ao usuário que o escreveu em um campo user_id :

{ "_id": ObjectID("17c9812acff9ac0bba018cc1"), "user_id": ObjectID("45b83bda421238c76f5c1969"), "date: ISODate("2016-09-05T03:05:00.123Z"), "text": "My life story so far", "rating": "important"}

queremos agora mostrar os últimos vinte posts com uma classificação” importante ” de todos os usuários em ordem cronológica inversa. Cada documento devolvido deve conter o texto, a hora do post e o nome e país do usuário associado.

a consulta agregada MongoDB é aprovada por uma série de operadores de oleodutos que definem cada operação em ordem. Primeiro, precisamos extrair todos os documentos da coleção post que têm a classificação correta usando o filtro $match :

{ "$match": { "rating": "important" } }

agora Temos de classificar a correspondência de itens para inverter a ordem de data usando o $sort operador:

{ "$sort": { "date": -1 } }

Desde que requerem apenas vinte posts, podemos aplicar um $limit palco para o MongoDB só precisa processar os dados que deseja:

{ "$limit": 20 }

podemos agora juntar-se a dados do user coleção usando o novo $lookup operador. Exige um objeto com quatro parâmetros:

  • localField: o campo de pesquisa no documento de entrada
  • from: a coleção para participar
  • foreignField: o campo de pesquisa na from collection
  • as: o nome do campo de saída.O nosso operador é, portanto,:
    { "$lookup": { "localField": "user_id", "from": "user", "foreignField": "_id", "as": "userinfo"} }

    Isto irá criar um novo campo na nossa saída chamado userinfo. Ele contém um array onde cada valor é o correspondente ao documento user :

    "userinfo": 

    temos uma relação de um para um entre os post.user_id e user._id, uma vez que um post só pode ter um autor. Portanto, nosso array userinfo conterá apenas um item. Podemos usar o operador $unwind para desconstruí – lo em um sub-documento:

    { "$unwind": "$userinfo" }

    A saída agora será convertido para um mais prático formato que pode ter mais operadores aplicada:

    "userinfo": { "name": "User One", "email: "[email protected]", …}

    Finalmente, pode-se voltar o texto, o tempo do post, o nome do usuário e do país usando um $project estágio do pipeline:

    { "$project": { "text": 1, "date": 1, "userinfo.name": 1, "userinfo.country": 1} }

    juntando Tudo

    Nossa última consulta agregada corresponde posts, classifica em ordem, limites para as últimas vinte itens, junta-se os dados do usuário, achata o usuário matriz e retorna campos necessários apenas. O comando completo:

    db.post.aggregate();

    o resultado é uma coleção de até vinte documentos. Por exemplo:

    óptimo! Finalmente posso mudar para NoSQL!

    MongoDB $lookup é útil e poderoso, mas mesmo este exemplo básico requer uma consulta agregada complexa. Não é um substituto para a cláusula de adesão mais poderosa oferecida no SQL. Nem MongoDB oferece restrições; se um documento user for suprimido, os documentos órfãos post permanecerão.Idealmente, o operador de $lookup deve ser requerido com pouca frequência. Se você precisa muito, você está possivelmente usando o armazenamento de dados errado…

    se você tem dados relacionais, use uma base de dados relacional (SQL)!

    dito isto, $lookup é uma adição bem-vinda ao MongoDB 3.2. Ele pode superar algumas das questões mais frustrantes ao usar pequenas quantidades de dados relacionais em um banco de dados NoSQL.

You might also like

Deixe uma resposta

O seu endereço de email não será publicado.