Menu Docs
Página inicial do Docs
/
Manual do MongoDB
/ /

Evite arrays ilimitadas

Nesta página

  • Exemplo
  • Padrão de subconjunto
  • Dados de referência
  • Use $lookup para unir um campo de array
  • Saiba mais

Armazenar arrays como valores de campo permite incorporar dados e garantir que os dados acessados juntos sejam armazenados juntos. No entanto, se você não limitar o número de elementos em uma array, seus documentos poderão exceder o 16limite de tamanho do documento MB BSON. Uma array ilimitada pode sobrecarregar os recursos do aplicação e diminuir o desempenho do índice.

Em vez de incorporar conjuntos de dados inteiros, use a criação de subconjuntos e a referência a arrays vinculadas, o que pode melhorar o desempenho e manter tamanhos de documento gerenciáveis. Ao subconjunto de dados, você seleciona somente as partes necessárias dos dados para trabalhar, o que reduz o uso da memória e o tempo de processamento ao focar somente nos dados relevantes. Ao fazer referência a dados, você vincula a fontes de dados externas em vez de incorporá-las diretamente em seus documentos. Essa abordagem melhora o desempenho e reduz o tamanho do documento . Ao usar subconjunto e referência, você pode vincular matrizes e gerenciar sua data com mais eficiência.

Considere o seguinte esquema que rastreia avaliações de livros para um aplicação de biblioteca. O esquema inicial utiliza uma array para o campo reviews .

{
title: "Harry Potter",
author: "J.K. Rowling",
publisher: "Scholastic",
reviews: [
{
user: "Alice",
review: "Great book!",
rating: 5
},
{
user: "Bob",
review: "Didn't like it!",
rating: 1
},
{
user: "Charlie",
review: "Not bad, but could be better.",
rating: 3
}
]
}

Neste esquema, o campo reviews é uma array ilimitada. Toda vez que uma nova revisão é criada para este livro, o aplicação adiciona um novo subdocumento à array reviews . À medida que mais revisões são adicionadas, a array pode ficar muito grande e sobrecarregar os recursos do aplicação .

Neste exemplo, o aplicação da biblioteca só precisa mostrar três avaliações de livros por livro. Para evitar arrays ilimitadas, você pode usar o padrão de design de subconjunto ou referências de documento, dependendo do seu caso de uso.

A subconjunto de dados é melhor para quando você precisa de acesso rápido a dados que não são atualizados com frequência. Usando o padrão de subconjunto, você pode incorporar três das revisões no documento do livro para retornar todas as informações necessárias em uma única operação. As outras avaliações são armazenadas em uma coleção reviews separada. Esse padrão de design de esquema oferece os seguintes benefícios:

  • Elimine o array ilimitado

  • Controle o tamanho do documento

  • Evite o uso de várias queries

A collection books :

db.books.insertOne( [
{
title: "Harry Potter",
author: "J.K. Rowling",
publisher: "Scholastic",
reviews: [
{
reviewer: "Alice",
review: "Great book!",
rating: 5
},
{
reviewer: "Charlie",
review: "Didn't like it.",
rating: 1
},
{
reviewer: "Bob",
review: "Not bad, but could be better.",
rating: 3
}
],
}
] )

A collection reviews :

db.reviews.insertMany( [
{
reviewer: "Jason",
review: "Did not enjoy!",
rating: 1
},
{
reviewer: "Pam",
review: "Favorite book!",
rating: 5
},
{
reviewer: "Bob",
review: "Not bad, but could be better.",
rating: 3
}
] )

Essa abordagem duplica dados, o que faz com que as atualizações sejam caras. Essa abordagem é melhor se as avaliações não forem atualizadas com frequência.

A referência de dados é melhor para quando você precisa gerenciar conjuntos de dados grandes ou atualizados com frequência sem aumentar o tamanho dos documento .

Para fazer referência a dados, armazene avaliações em uma collection separada e adicione um campo review_id aos documentos na collection reviews . Use o campo review_id para fazer referência às avaliações na coleção books .

Essa abordagem resolve o problema da array ilimitada, mas introduz latência porque você precisa consultar a collection reviews para recuperar informações de avaliação da collection books . Dependendo do seu caso de uso, essa latência adicional pode ser uma compensação aceitável para evitar os problemas causados por arrays ilimitadas.

A collection books :

db.books.insertMany( [
{
title: "Harry Potter",
author: "J.K. Rowling",
publisher: "Scholastic",
reviews: ["review1", "review2", "review3"]
},
{
title: "Pride and Prejudice",
author: "Jane Austen",
publisher: "Penguin",
reviews: ["review4", "review5"]
}
] )

A collection reviews :

db.reviews.insertMany( [
{
review_id: "review1",
reviewer: "Jason",
review: "Did not enjoy!",
rating: 1
},
{
review_id: "review2",
reviewer: "Pam",
review: "Favorite book!",
rating: 5
},
{
review_id: "review3",
reviewer: "Bob",
review: "Not bad, but could be better.",
rating: 3
},
{
review_id: "review4",
reviewer: "Tina",
review: "Amazing!",
rating: 5
},
{
review_id: "review5",
reviewer: "Jacob",
review: "A little overrated",
rating: 4,
}
] )

Se suas informações de books e reviews estiverem armazenadas em collections separadas, o aplicação precisará executar uma operação de $lookup para unir os dados.

A seguinte operação de agregação une a coleção books e reviews do exemplo anterior.

db.books.aggregate( [
{
$lookup: {
from: "reviews",
localField: "reviews",
foreignField: "review_id",
as: "reviewDetails"
}
}
] )

A operação retorna o seguinte:

[
{
_id: ObjectId('665de81eeda086b5e22dbcc9'),
title: 'Harry Potter',
author: 'J.K. Rowling',
publisher: 'Scholastic',
reviews: [ 'review1', 'review2', 'review3' ],
reviewDetails: [
{
_id: ObjectId('665de82beda086b5e22dbccb'),
review_id: 'review1',
reviewer: 'Jason',
review: 'Did not enjoy!',
rating: 1
},
{
_id: ObjectId('665de82beda086b5e22dbccc'),
review_id: 'review2',
reviewer: 'Pam',
review: 'Favorite book!',
rating: 5
},
{
_id: ObjectId('665de82beda086b5e22dbccd'),
review_id: 'review3',
reviewer: 'Bob',
review: 'Not bad, but could be better.',
rating: 3
} ]
},
{
_id: ObjectId('665de81eeda086b5e22dbcca'),
title: 'Pride and Prejudice',
author: 'Jane Austen',
publisher: 'Penguin',
reviews: [ 'review4', 'review5' ],
reviewDetails: [
{
_id: ObjectId('665de82beda086b5e22dbcce'),
review_id: 'review4',
reviewer: 'Tina',
review: 'Amazing!',
rating: 5
},
{
_id: ObjectId('665de82beda086b5e22dbccf'),
review_id: 'review5',
reviewer: 'Jacob',
review: 'A little overrated',
rating: 4
} ]
}
]

Neste exemplo, a operação $lookup une a collection books à collection reviews usando a array reviews no documento do livro e o campo review_id nos documentos das avaliações. O documento reviewDetails armazena os dados combinados.

Voltar

Antipadrão de design de esquema