Logo

dev-resources.site

for different kinds of informations.

Detectando índices no MongoDB

Published at
8/28/2023
Categories
mongodb
index
atlas
nosql
Author
delbussoweb
Categories
4 categories in total
mongodb
open
index
open
atlas
open
nosql
open
Author
11 person written this
delbussoweb
open
Detectando índices no MongoDB

Detecção de Índices

Será necessário?

Fala pessoALL, em algumas situações precisaremos identificar índices por algum motivo, seja para uma documentação do ambiente ou até mesmo para a reprodução desses índices em outro cluster, como por exemplo desenvolvimento, homologação ou até mesmo para colocá-los em produção. Ter um script que identifique estes índices é importante em vários sentidos e sempre bom tê-lo à mão.

No meu caso essa necessidade surgiu para efeito de documentação, principalmente para identificar se algumas coleções do banco de dados estavam com índices do tipo TTL, muito utilizados para o expurgo automático de dados.

Conectando

O cluster utilizado aqui está no MongoDB Atlas e se você não tem ainda um ambiente lá para testes pode criar um cluster totalmente free aqui.

Vamos utilizar o mongosh que é uma interface completa para administração do MongoDB, vou demonstrar passo-a-passo e por fim juntar tudo para criar o nosso script de saída. Também é importante ressaltar que os comandos à seguir foram executados na versão 7.0 do MongoDB.

mongosh "mongodb+srv://<seu_cluster>/myFirstDatabase" --apiVersion 1 --username <seu_usuario>
Enter fullscreen mode Exit fullscreen mode

Listando os databases

Aqui é importante ressaltar que o usuário utilizado para a conexão / execução do script deve ter os privilégios necessários para algumas tarefas, como listar os databases, coleções e por fim os índices. Veja mais sobre as permissões no MongoDB neste link.

var myDBs = db.adminCommand({ listDatabases: 1 }).databases.map(db => db.name);
myDBs.forEach(myDB => {
    print(myDB);
});
Enter fullscreen mode Exit fullscreen mode

Listando as coleções

Agora com os nomes dos databases de nosso cluster, podemos adicionar mais uma etapa e listar o nome das coleções de cada um deles. Note que não queremos listar as coleções dos databases admin e nem local, para isso, vamos adicionar uma condição que "exclua" esses databases.

var myDBs = db.adminCommand({ listDatabases: 1 }).databases.map(db => db.name);
myDBs.forEach(myDB => {
    if (myDB !== 'admin' && myDB !== 'local') {
        db = db.getSiblingDB(myDB);
        print(`Coleções no banco de dados ${myDB}:`);
        db.getCollectionNames().forEach(collectionName => {
            print(`- ${collectionName}`);
        });
    }
});
Enter fullscreen mode Exit fullscreen mode

Listando os índices

Agora, vamos finalmente listar os índices de cada uma das coleções:

var myDBs = db.adminCommand({ listDatabases: 1 }).databases.map(db => db.name);
myDBs.forEach(myDB => {
    if (myDB !== 'admin' && myDB !== 'local') {
        db = db.getSiblingDB(myDB);
        print(`Coleções no banco de dados ${myDB}:`);
        db.getCollectionNames().forEach(collectionName => {
            print(`- ${collectionName}`);
            let indexes = db.getCollection(collectionName).getIndexes();
            indexes.forEach(index => {
                print(`  - ${index.name} (${JSON.stringify(index)})`);
            });
        });
    }
});
Enter fullscreen mode Exit fullscreen mode

Note que para cada índice temos seu nome e também as propriedades que compõem cada um deles. Isso é importante não só para a identificação dessas propriedades, mas também para gerar uma saída para a criação de cada um deles.

Adicionando o createIndex()

Vamos modificar um pouco o script para que ele nos dê o comando para a criação de cada um desses índices:

var myDBs = db.adminCommand({ listDatabases: 1 }).databases.map(db => db.name);
myDBs.forEach(myDB => {
    if (myDB !== 'admin' && myDB !== 'local') {
        db = db.getSiblingDB(myDB);
        print(`Coleções no banco de dados ${myDB}:`);
        db.getCollectionNames().forEach(collectionName => {
            print(`- ${collectionName}`);
            let indexes = db.getCollection(collectionName).getIndexes();
            indexes.forEach(index => {
                print(`  - ${index.name} (${JSON.stringify(index)})`);
                print(`    -- create: db.getCollection("${collectionName}").createIndex(${JSON.stringify(index.key)}, ${JSON.stringify(index)});`)
            });
        });
    }
});
Enter fullscreen mode Exit fullscreen mode

Podemos também modificar um pouco mais para que o índice _id não gere o script para a criação:

var myDBs = db.adminCommand({ listDatabases: 1 }).databases.map(db => db.name);
myDBs.forEach(myDB => {
    if (myDB !== 'admin' && myDB !== 'local') {
        db = db.getSiblingDB(myDB);
        print(`Coleções no banco de dados ${myDB}:`);
        db.getCollectionNames().forEach(collectionName => {
            print(`- ${collectionName}`);
            let indexes = db.getCollection(collectionName).getIndexes();
            indexes.forEach(index => {
                if(index.name !== "_id_"){
                    print(`  - ${index.name} (${JSON.stringify(index)})`);
                    print(`    -- create: db.getCollection("${collectionName}").createIndex(${JSON.stringify(index.key)}, ${JSON.stringify(index)});`)
                }
            });
        });
    }
});
Enter fullscreen mode Exit fullscreen mode

Identificando uma propriedade do índice

Ok, chegamos até aqui, mas e se quisermos listar somente os índices com a propriedade TTL (como se deu a origem desse post)?

var myDBs = db.adminCommand({ listDatabases: 1 }).databases.map(db => db.name);
myDBs.forEach(myDB => {
    if (myDB !== 'admin' && myDB !== 'local') {
        db = db.getSiblingDB(myDB);
        print(`Coleções no banco de dados ${myDB}:`);
        db.getCollectionNames().forEach(collectionName => {
            print(`- ${collectionName}`);
            let indexes = db.getCollection(collectionName).getIndexes();
            indexes.forEach(index => {
                if(index.name !== "_id_"){
                    if (index.expireAfterSeconds !== undefined) {
                        print(`  - ${index.name} (${JSON.stringify(index)})`);
                        print(`    -- create: db.getCollection("${collectionName}").createIndex(${JSON.stringify(index.key)}, ${JSON.stringify(index)});`)
                    }
                }
            });
        });
    }
});
Enter fullscreen mode Exit fullscreen mode

Juntando tudo

Ufa, quanta coisa! Agora vamos juntar tudo para que nosso script seja realmente funcional em três pontos:

  • listar todos os índices (exceto o _id) de cada coleção de cada base de dados;
  • gerar o comando para a criação de cada um deles;
  • e por fim, somente os índices TTL. ### Todos os índices
var myDBs = db.adminCommand({ listDatabases: 1 }).databases.map(db => db.name);
myDBs.forEach(myDB => {
    if (myDB !== 'admin' && myDB !== 'local') {
        db = db.getSiblingDB(myDB);
        print(`use ${myDB};`);
        db.getCollectionNames().forEach(collectionName => {
            let indexes = db.getCollection(collectionName).getIndexes();
            indexes.forEach(index => {
                if (index.expireAfterSeconds !== undefined) {
                        printjson(`db.getCollection("${collectionName}").createIndex(${JSON.stringify(index.key)}, ${JSON.stringify(index)});`)
                }
            });
        });
    }
});
Enter fullscreen mode Exit fullscreen mode

Saída para arquivo

Aqui para facilitar, colocaremos o conteúdo de nosso script em um arquivo chamado verifyIndex.js, você pode criar esse arquivo como preferir. Com isso teremos um arquivo de saída chamado outputIndex.js.

  • crie o arquivo verifyIndex.js
cat << 'index' | tee verifyIndex.js
var myDBs = db.adminCommand({ listDatabases: 1 }).databases.map(db => db.name);
myDBs.forEach(myDB => {
    if (myDB !== 'admin' && myDB !== 'local') {
        db = db.getSiblingDB(myDB);
        print(`use ${myDB};`);
        db.getCollectionNames().forEach(collectionName => {
            let indexes = db.getCollection(collectionName).getIndexes();
            indexes.forEach(index => {
                if(index.name !== "_id_"){
                    printjson(`db.getCollection("${collectionName}").createIndex(${JSON.stringify(index.key)}, ${JSON.stringify(index)});`)
                }
            });
        });
    }
});
index
Enter fullscreen mode Exit fullscreen mode
  • carregue o arquivo utilizando o mongosh. Aqui utilizamos os seguintes parâmetros:
    • --file indicando o arquivo que será carregado
    • --quiet para que o arquivo de saída não contenha nenhum registro sobre a execução do mongosh, como abertura de conexão e etc.
    • e finalmente a saída será escrita no arquivo outputIndex.js
mongosh "mongodb+srv://<user>:<password>@<seu_cluster>/test" --file verifyIndex.js --quiet > outputIndex.js
Enter fullscreen mode Exit fullscreen mode

Saída para arquivo somente dos índices TTL

cat << 'index' | tee verifyIndex.js
myDBs.forEach(myDB => {
    if (myDB !== 'admin' && myDB !== 'local') {
        db = db.getSiblingDB(myDB);
        print(`use ${myDB};`);
        db.getCollectionNames().forEach(collectionName => {
            let indexes = db.getCollection(collectionName).getIndexes();
            indexes.forEach(index => {
                if (index.expireAfterSeconds !== undefined) {
                        printjson(`db.getCollection("${collectionName}").createIndex(${JSON.stringify(index.key)}, ${JSON.stringify(index)});`)
                }
            });
        });
    }
});
Enter fullscreen mode Exit fullscreen mode

Conclusão

É isso pessoALL... como sempre destaco em meus posts, existem diversas maneiras de fazer isso, uma delas é inclusive utilizando Python (o que particularmente eu gosto bastante), e prometo compartilhar o script mais a frente!

Espero que tenham gostado e fiquem à vontade para compartilhar!

Um abraço e até mais!

index Article's
30 articles in total
Favicon
Avoiding the Pitfalls of Duplicate Indexes in MySQL
Favicon
SQL Performance: A Deep Dive into Indexing with examples
Favicon
Tried-and-True Methods to Immediately Get Google to Index Your Website
Favicon
Mysql Database Index Explained for Beginners
Favicon
Database: Indexing issues with random UUIDs
Favicon
Nol indekslangan to'plamlar
Favicon
Quantitative trading strategy using trading volume weighted index
Favicon
Apache SOLR
Favicon
How to Replace Character at Nth Index in Python String
Favicon
Postgres partitioning performance: Hash vs. List
Favicon
A Novice Guide to Azure AI Search
Favicon
PostgreSQL index Correlation with UPDATE
Favicon
fetch vs index methods when working with arrays in Ruby
Favicon
How To Quickly Define an Efficient SQL Index for GROUP BY Queries
Favicon
Optimize Mongo DB Performance By Adding Indexes to Your Collection
Favicon
Optimizing Database Performance with Concatenated Indexes
Favicon
A Guide to Sargable Queries
Favicon
The Most Annoying Optimizer Fail in Postgres ✅ Best index solved it.
Favicon
To speed up the search process, let’s set an index for array data within a JSON-formatted column
Favicon
How To Get Google To Index Your Site Fast in 2024 | Index your website Readmorr.com
Favicon
Detectando índices no MongoDB
Favicon
10 Best Practices While Using MongoDB Indexes
Favicon
Summarize Heap-Only Tuple and Index-Only Scans in PostgreSQL
Favicon
Uncovering the Significance of Indexes in Apache AGE
Favicon
Partial Indexes in MongoDB: A Brief Overview
Favicon
Making sure our database queries are fast
Favicon
Principles of Database Index Design
Favicon
The Simple SQL Question You May Be Asked on Interview and Fail
Favicon
Index usage monitoring in YugabyteDB & PostgreSQL
Favicon
Database Indexing with PostgreSQL

Featured ones: