Diferenças funcionais: Amazon DocumentDB e MongoDB - Amazon DocumentDB

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Diferenças funcionais: Amazon DocumentDB e MongoDB

Abaixo estão as diferenças funcionais entre o Amazon DocumentDB (compatível com MongoDB) e o MongoDB.

Benefícios funcionais do Amazon DocumentDB

Transações implícitas

No Amazon DocumentDB, todas as instruções CRUD (findAndModify, update, insert, delete) garantem atomicidade e consistência, até mesmo para operações que modificam vários documentos. Agora, com o lançamento do Amazon DocumentDB 4.0, há suporte para transações explícitas que fornecem propriedades ACID para operações com várias instruções e várias coleções. Para obter mais informações sobre o uso de transações no Amazon DocumentDB, consulte Transações no Amazon DocumentDB.

Veja a seguir exemplos de operações no Amazon DocumentDB que modificam vários documentos que satisfazem ambos os comportamentos atômico e consistente.

db.miles.update( { "credit_card": { $eq: true } }, { $mul: { "flight_miles.$[]": NumberInt(2) } }, { multi: true } )
db.miles.updateMany( { "credit_card": { $eq: true } }, { $mul: { "flight_miles.$[]": NumberInt(2) } } )
db.runCommand({ update: "miles", updates: [ { q: { "credit_card": { $eq: true } }, u: { $mul: { "flight_miles.$[]": NumberInt(2) } }, multi: true } ] })
db.products.deleteMany({ "cost": { $gt: 30.00 } })
db.runCommand({ delete: "products", deletes: [{ q: { "cost": { $gt: 30.00 } }, limit: 0 }] })

As operações individuais que compõem operações em massa, como updateMany e deleteMany, são atômicas, mas a própria operação em massa não é atômica. Por exemplo, a totalidade da operação insertMany será atômica se as operações de inserção individuais forem executadas com êxito sem erros. Se um erro for encontrado em uma operação insertMany, cada instrução de inserção individual na operação insertMany será executada como uma operação atômica. Se você precisar de propriedades ACID para as operações insertMany, updateMany e deleteMany, é recomendável usar uma transação.

Diferenças funcionais atualizadas

O Amazon DocumentDB continua a melhorar a compatibilidade com o MongoDB, trabalhando retroativamente com as capacidades que nossos clientes nos pedem para criar. Esta seção contém as diferenças funcionais removidas do Amazon DocumentDB para facilitar as migrações e a criação de aplicativos para nossos clientes.

Indexação de matriz

A partir de 23 de abril de 2020, o Amazon DocumentDB passa a oferecer suporte à capacidade de indexar matrizes maiores que 2.048 bytes. O limite para um item individual em uma matriz ainda permanece como 2.048 bytes, o que é consistente com MongoDB.

Se você estiver criando um novo índice, nenhuma ação será necessária para aproveitar a funcionalidade aprimorada. Se tiver um índice existente, você pode aproveitar a funcionalidade aprimorada, eliminando o índice e recriando-o. A versão atual do índice com os recursos aprimorados é "v" : 3.

nota

Para clusters de produção, a eliminação do índice pode ter impacto no desempenho do aplicativo. Recomendamos que você teste primeiro e prossiga com cuidado ao fazer alterações em um sistema de produção. Além disso, o tempo que levará para recriar o índice será uma função do tamanho geral dos dados da coleção.

É possível consultar a versão dos índices usando o seguinte comando.

db.collection.getIndexes()

A saída dessa operação é semelhante à seguinte. Nesta saída, a versão do índice é "v" : 3, que é a versão mais atual.

[ { "v" : 3, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.test" } ]

Índices de várias chaves

A partir de 23 de abril de 2020, o Amazon DocumentDB passa a oferecer suporte à capacidade de criar um índice composto com várias chaves na mesma matriz.

Se você estiver criando um novo índice, nenhuma ação será necessária para aproveitar a funcionalidade aprimorada. Se tiver um índice existente, você pode aproveitar a funcionalidade aprimorada, eliminando o índice e recriando-o. A versão atual do índice com os recursos aprimorados é "v" : 3.

nota

Para clusters de produção, a eliminação do índice pode ter impacto no desempenho do aplicativo. Recomendamos que você teste primeiro e prossiga com cuidado ao fazer alterações em um sistema de produção. Além disso, o tempo que levará para recriar o índice será uma função do tamanho geral dos dados da coleção.

É possível consultar a versão dos índices usando o seguinte comando.

db.collection.getIndexes()

A saída dessa operação é semelhante à seguinte. Nesta saída, a versão do índice é "v" : 3, que é a versão mais atual.

[ { "v" : 3, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.test" } ]

Caracteres nulos em strings

Desde 22 de junho de 2020, o Amazon DocumentDB passou a oferecer suporte a caracteres nulos ( '\0' ) em strings.

Controle de acesso com base em função

Desde 26 de março de 2020, o Amazon DocumentDB oferece suporte ao controle de acesso baseado em função (RBAC) para funções internas. Para saber mais, consulte Controle de acesso com base em função.

Indexação de $regex

Desde 22 de junho de 2020, o Amazon DocumentDB passou a oferecer suporte à capacidade de operadores $regex utilizarem um índice.

Para utilizar um índice com o operador $regex, é necessário usar o comando hint(). Ao usar hint(), é necessário especificar o nome do campo no qual você está aplicando o $regex. Por exemplo, se você tiver um índice no campo product com o nome do índice como p_1, db.foo.find({product: /^x.*/}).hint({product:1}) usará o índice p_1, mas não usará o índice db.foo.find({product: /^x.*/}).hint(“p_1”). É possível verificar se um índice é escolhido utilizando o comando explain() ou usando o profiler para registrar em log consultas lentas. Por exemplo, db.foo.find({product: /^x.*/}).hint(“p_1”).explain().

nota

O método hint() só pode ser usado com um índice de cada vez.

O uso de um índice para uma consulta $regex é otimizado para consultas de regex que usam um prefixo e não especificam as opções de regex I, m ou o.

Ao usar um índice com $regex, é recomendável criar um índice em campos altamente seletivos onde o número de valores duplicados é inferior a 1% do número total de documentos na coleção. Por exemplo, se sua coleção contiver 100.000 documentos, crie índices somente em campos em que o mesmo valor ocorrer 1000 vezes ou menos.

Projeção para documentos aninhados

Há uma diferença funcional entre o Amazon DocumentDB e o MongoDB com o operador $project na versão 3.6 que foi resolvida no Amazon DocumentDB 4.0, mas que permanecerá sem suporte no Amazon DocumentDB 3.6.

O Amazon DocumentDB 3.6 só considera o primeiro campo em um documento aninhado ao aplicar uma projeção e o MongoDB 3.6 também analisará subdocumentos e aplicará a projeção a cada subdocumento.

Por exemplo: se a projeção for “a.b.c”: 1, o comportamento funcionará conforme o esperado no Amazon DocumentDB e no MongoDB. No entanto, se a projeção for {a:{b:{c:1}}}, o Amazon DocumentDB 3.6 aplicará a projeção somente a a e não a b ou c. No Amazon DocumentDB 4.0, a projeção {a:{b:{c:1}}} será aplicada a a, b e c.

Diferenças funcionais com o MongoDB

O Amazon DocumentDB não oferece suporte a $vectorSearch como um operador independente. Em vez disso, temos suporte para vectorSearch dentro do operador $search. Para obter mais informações, consulte Pesquisa vetorial para Amazon DocumentDB.

OpCountersCommand

O comportamento OpCountersCommand do Amazon DocumentDB se desvia do opcounters.command do MongoDB da seguinte forma:

  • O opcounters.command do MongoDB conta todos os comandos, exceto inserir, atualizar e excluir, enquanto que o OpCountersCommand do Amazon DocumentDB também exclui o comando find.

  • O Amazon DocumentDB considera alguns comandos internos com relação a OpCountersCommand.

Bancos de dados e coleções de administradores

O Amazon DocumentDB não oferece suporte ao banco de dados de administrador ou local nem às coleções do MongoDB system.* ou startup_log respectivamente.

cursormaxTimeMS

No Amazon DocumentDB, cursor.maxTimeMS redefine o contador de cada solicitação getMore. Portanto, se for especificado 3.000 ms maxTimeMS, a consulta irá demorar 2.800 ms e cada solicitação getMore subsequente irá demorar 300 ms, depois, o cursor não atingirá o tempo limite. O cursor só atingirá o tempo limite quando uma única operação, seja a consulta ou uma determinada solicitação getMore, demorar mais do que o maxTimeMS especificado. Além disso, o varredor que verifica o tempo de execução do cursor é executado em uma granularidade de cinco (5) minutos.

explain()

O Amazon DocumentDB emula a API do MongoDB 4.0 em um mecanismo de banco de dados com propósito específico que utiliza um sistema de armazenamento distribuído, tolerante a falhas e de autorrecuperação. Como resultado, os planos de consulta e a saída de explain() podem diferir entre o Amazon DocumentDB e o MongoDB. Os clientes que desejam ter controle sobre seu plano de consulta podem usar o operador $hint para impor a seleção de um índice preferencial.

Restrições de nome de campo

O Amazon DocumentDB não oferece suporte a pontos “.” em um campo de nome de documento, por exemplo, db.foo.insert({‘x.1’:1}).

O Amazon DocumentDB também não oferece suporte ao prefixo $ em campos de nome.

Por exemplo, tente o seguinte comando no Amazon DocumentDB ou no MongoDB:

rs0:PRIMARY< db.foo.insert({"a":{"$a":1}})

O MongoDB retornará o seguinte:

WriteResult({ "nInserted" : 1 })

O Amazon DocumentDB retornará um erro:

WriteResult({ "nInserted" : 0, "writeError" : { "code" : 2, "errmsg" : "Document can't have $ prefix field names: $a" } })
nota

Há uma exceção a essa diferença funcional. Os seguintes nomes de campo que começam com o prefixo $ foram incluídos na lista branca e podem ser usados com êxito no Amazon DocumentDB: $id, $ref e $db.

Compilações de índice

O Amazon DocumentDB permite que apenas uma compilação de índice ocorra em uma coleção a qualquer momento. Seja em primeiro plano ou em segundo plano. Se operações como createIndex() ou dropIndex() ocorrerem na mesma coleção quando uma compilação de índice estiver em andamento no momento, ocorrerá uma falha na operação que você tentou executar recentemente.

Por padrão, as compilações de índices no Amazon DocumentDB e na versão 4.0 do MongoDB ocorrem em segundo plano. As versões 4.2 e posteriores do MongoDB ignoram a opção de construção do índice em segundo plano se especificada para createIndexes ou seus auxiliares de shell createIndex() e createIndexes().

Um índice de Tempo de vida (TTL) começará a extinguir a validade de documentos depois que o índice de compilação for concluído.

Pesquisa com chave vazia no caminho

Quando você pesquisa com uma chave que inclui uma string vazia como parte do caminho (por exemplo, x., x..b) e o objeto tem um caminho de chaves de string vazio (por exemplo, {"x" : [ { "" : 10 }, { "b" : 20 } ]}) dentro de uma matriz, o Amazon DocumentDB retornará resultados diferentes do que se você executasse a mesma pesquisa no MongoDB.

No MongoDB, a pesquisa do caminho de chaves vazio dentro da matriz funciona conforme o esperado quando a chave de string vazia não está no final da pesquisa do caminho. No entanto, quando a chave de string vazia está no final da pesquisa do caminho, ela não examina a matriz.

No entanto, no Amazon DocumentDB, somente o primeiro elemento dentro da matriz é lido, pois getArrayIndexFromKeyString converte uma string vazia em 0, e, então, a pesquisa por chaves de string é tratada como uma pesquisa de índice de matriz.

APIs, operações e tipos de dados do MongoDB

O Amazon DocumentDB é compatível com as APIs do MongoDB 3.6 e 4.0. Para obter uma lista atualizada das funcionalidades compatíveis, consulte APIsMongoDB, operações e tipos de dados compatíveis no Amazon DocumentDB.

Utilitários mongodump e mongorestore

O Amazon DocumentDB não oferece suporte a um banco de dados de administrador e, portanto, não despeja nem restaura o banco de dados de administrador ao usar os utilitários mongodump ou mongorestore. Ao criar um novo banco de dados no Amazon DocumentDB usando mongorestore, é necessário recriar as funções de usuário, além da operação de restauração.

nota

Recomendamos o MongoDB Database Tools até a versão 100.6.1, inclusive, para o Amazon DocumentDB. Você pode acessar os downloads do MongoDB Database Tools aqui.

Ordenação de resultados

O Amazon DocumentDB não garante a ordenação de resultados implícita dos conjuntos de resultados. Para garantir a ordenação de um conjunto de resultados, especifique explicitamente uma ordem de classificação usando sort().

O exemplo a seguir classifica os itens na coleção de inventário em ordem decrescente com base no campo de estoque.

db.inventory.find().sort({ stock: -1 })

Ao usar o estágio de agregação $sort, a ordem de classificação não é preservada, a menos que o estágio $sort seja o último estágio no pipeline de agregação. Ao usar o estágio de agregação $sort em combinação com o estágio de agregação $group, o estágio de agregação $sort só é aplicado aos acumuladores $first e $last. No Amazon DocumentDB 4.0, foi adicionado suporte para $push para respeitar a ordem de classificação do estágio $sort anterior.

Gravações repetíveis

A partir dos drivers compatíveis com o MongoDB 4.2, as gravações repetíveis são ativadas por padrão. No entanto, o Amazon DocumentDB atualmente não oferece suporte a gravações repetíveis. A diferença funcional se manifestará em uma mensagem de erro semelhante à seguinte.

{"ok":0,"errmsg":"Unrecognized field: 'txnNumber'","code":9,"name":"MongoError"}

Gravações repetíveis que podem ser desabilitadas por meio da string de conexão (por exemplo, MongoClient("mongodb://my.mongodb.cluster/db?retryWrites=false")) ou do argumento de palavra-chave do construtor MongoClient (por exemplo, MongoClient("mongodb://my.mongodb.cluster/db", retryWrites=False)).

Veja a seguir um exemplo de Python que desabilita gravações repetíveis na string de conexão.

client = pymongo.MongoClient('mongodb://<username>:<password>@docdb-2019-03-17-16-49-12.cluster-ccuszbx3pn5e.us-east-1.docdb.amazonaws.com:27017/?replicaSet=rs0',w='majority',j=True,retryWrites=False)

Índice esparso

Para usar um índice esparso que você criou em uma consulta, é necessário usar a cláusula $exists nos campos que abrangem o índice. Se você omitir $exists, o Amazon DocumentDB não usará o índice esparso.

Veja um exemplo a seguir.

db.inventory.count({ "stock": { $exists: true }})

Para índices esparsos de várias chaves, o Amazon DocumentDB não oferecerá suporte a uma restrição de chave exclusiva se a pesquisa de um documento resultar em um conjunto de valores e apenas um subconjunto dos campos indexados estiver ausente. Por exemplo, createIndex({"a.b" : 1 }, { unique : true, sparse :true }) não tem suporte, dada a entrada de "a" : [ { "b" : 2 }, { "c" : 1 } ], já que "a.c" é armazenado no índice.

Usar $elemMatch dentro de uma expressão $all

No momento, o Amazon DocumentDB não oferece suporte ao uso do operador $elemMatch dentro de uma expressão $all. Como solução alternativa, é possível usar o operador $and com $elemMatch da seguinte forma.

Operação original:

db.col.find({ qty: { $all: [ { "$elemMatch": { part: "xyz", qty: { $lt: 11 } } }, { "$elemMatch": { num: 40, size: "XL" } } ] } })

Operação atualizada:

db.col.find({ $and: [ { qty: { "$elemMatch": { part: "xyz", qty: { $lt: 11 } } } }, { qty: { "$elemMatch": { qty: 40, size: "XL" } } } ] })

Indexação de $ne, $nin, $nor, $not, $exists e $elemMatch

Atualmente, o Amazon DocumentDB não oferece suporte à capacidade de usar índices com os operadores $ne, $nin, $nor, $not, $exists e $distinct. Como resultado, o uso desses operadores resultará em verificação da coleção. Executar um filtro ou correspondência antes de usar um desses operadores reduzirá a quantidade de dados que precisam ser verificados e, portanto, pode melhorar o desempenho.

O Amazon DocumentDB adicionou suporte para varreduras de índice com o operador $elemMatch no Amazon DocumentDB 5.0 e em clusters elásticos. As varreduras de índice recebem suporte quando o filtro de consulta tem apenas um nível do filtro $elemMatch, mas não são suportadas se uma consulta aninhada $elemMatch for incluída.

Formato de consulta $elemMatch que oferece suporte a varreduras de índice no Amazon DocumentDB 5.0:

db.foo.find( { "a": {$elemMatch: { "b": "xyz", "c": "abc"} } })

Formato de consulta $elemMatch que não oferece suporte às varreduras de índice no Amazon DocumentDB 5.0:

db.foo.find( { "a": {$elemMatch: { "b": {$elemMatch: { "d": "xyz", "e": "abc"} }} } })

$lookup

O Amazon DocumentDB oferece suporte a correspondências de igualdade (por exemplo, junção externa esquerda) e também a subconsultas não correlacionadas, mas não oferece suporte a subconsultas correlacionadas.

Utilizando um índice com $lookup

Agora você pode utilizar um índice com o operador de estágio $lookup. Com base no seu caso de uso, há vários algoritmos de indexação que você pode usar para otimizar o desempenho. Esta seção explicará os diferentes algoritmos de indexação para $lookup e ajudará você a escolher o melhor para sua workload.

Por padrão, o Amazon DocumentDB utilizará o algoritmo de hash quando allowDiskUse:false for usado e a mesclagem de classificação quando allowDiskUse:true for usado .

nota

No momento, a opção allowDiskUse não é suportada pelo comando find. A opção só é suportada como parte da agregação. Recomendamos usar a estrutura de agregação com allowDiskUse:true para lidar com consultas grandes que possam exceder os limites de memória.

Para alguns casos de uso, pode ser melhor forçar o otimizador de consultas a usar um algoritmo diferente. Abaixo, estão os diferentes algoritmos de indexação que o operador de agregação $lookup pode utilizar:

  • Loop aninhado: um plano de loop aninhado geralmente é benéfico para uma workload se a coleção externa tiver menos de 1 GB e o campo na coleção externa tiver um índice. Se o algoritmo de loop aninhado estiver sendo usado, o plano de explicação mostrará o estágio como NESTED_LOOP_LOOKUP.

  • Mesclagem de classificação: um plano de mesclagem de classificação geralmente é benéfico para uma workload se a coleção externa não tiver um índice no campo usado na pesquisa e o conjunto de dados de trabalho não couber na memória. Se o algoritmo de mesclagem de classificação estiver sendo usado, o plano de explicação mostrará o estágio como SORT_LOOKUP.

  • Hash: um plano de hash geralmente é benéfico para uma workload se a coleção externa for < 1 GB e o conjunto de dados de trabalho couber na memória. Se o algoritmo de hash estiver sendo usado, o plano de explicação mostrará o estágio como HASH_LOOKUP.

Você pode identificar o algoritmo de indexação que está sendo usado pelo operador $lookup usando “explain” na consulta. Abaixo está um exemplo:

db.localCollection.explain(). aggregate( [ { $lookup: { from: "foreignCollection", localField: "a", foreignField: "b", as: "joined" } } ] output { "queryPlanner" : { "plannerVersion" : 1, "namespace" : "test.localCollection", "winningPlan" : { "stage" : "SUBSCAN", "inputStage" : { "stage" : "SORT_AGGREGATE", "inputStage" : { "stage" : "SORT", "inputStage" : { "stage" : "NESTED_LOOP_LOOKUP", "inputStages" : [ { "stage" : "COLLSCAN" }, { "stage" : "FETCH", "inputStage" : { "stage" : "COLLSCAN" } } ] } } } } }, "serverInfo" : { "host" : "devbox-test", "port" : 27317, "version" : "3.6.0" }, "ok" : 1 }

Como alternativa ao uso do método explain(), você pode usar o criador de perfil para revisar o algoritmo que está sendo utilizado com o uso do operador $lookup. Para obter mais informações sobre o criador de perfil, consulte . Definir o perfil das operações do Amazon DocumentDB.

Uso de uma planHint

Se você quiser forçar o otimizador de consultas a usar um algoritmo de indexação diferente com $lookup, você pode usar um planHint. Para fazer isso, use o comentário nas opções do estágio de agregação para forçar um plano diferente. Abaixo, está um exemplo de sintaxe do comentário:

comment : { comment : “<string>”, lookupStage : { planHint : “SORT” | “HASH” | "NESTED_LOOP" } }

Abaixo, está um exemplo de uso do planHint para forçar o otimizador de consultas a usar o algoritmo de indexação HASH:

db.foo.aggregate( [ { $lookup: { from: "foo", localField: "_id", foreignField: "_id", as: "joined" }, } ], { comment : "{ \\"lookupStage\\" : { \\"planHint\\": \\"HASH\\" }}"

Para testar qual algoritmo é melhor para sua workload, você pode usar o parâmetro executionStats do método explain para medir o tempo de execução do estágio $lookup enquanto modifica o algoritmo de indexação (ou seja, HASH/SORT/NESTED_LOOP).

O exemplo a seguir mostra como usar executionStats para medir o tempo de execução do estágio $lookup usando o algoritmo SORT.

db.foo.explain(“executionStats”).aggregate( [ { $lookup: { from: "foo", localField: "_id", foreignField: "_id", as: "joined" }, } ], { comment : "{ \\"lookupStage\\" : { \\"planHint\": \\"SORT\\" }}"