Menu Docs

Junção um para um

Neste tutorial, você pode aprender como usar o PyMongo para construir um pipeline de agregação, executar a agregação em uma coleção e imprimir os resultados concluindo e executando um aplicativo de exemplo.

Essa aggregation realiza uma junção de um para um. Uma união um a um ocorre quando um documento em uma collection tem um valor de campo que corresponde a um único documento em outra collection que tem o mesmo valor de campo. A agregação corresponde a esses documentos no valor do campo e combina informações de ambas as fontes em um resultado.

Dica

Uma união de um para um não exige que os documentos tenham um relacionamento de um para um. Para saber mais sobre esse relacionamento de dados, consulte o verbete do Wikipedia sobre Um-para-um (modelo de dados).

Este tutorial demonstra como combinar dados de uma collection que descreve informações do produto com outra collection que descreve solicitações de clientes. Os resultados mostram uma lista de todos os pedidos feitos em 2020 que inclui os detalhes do produto associados a cada pedido.

Este exemplo utiliza duas collection:

  • orders: contém documentos que descrevem pedidos individuais de produtos em uma loja

  • products: contém documentos que descrevem os produtos que uma loja vende

Um pedido só pode conter um produto, portanto, a agregação usa uma união de um para um para corresponder um documento do pedido ao documento do produto. As collection são unidas por um campo chamado product_id que existe em documento de ambas as collection.

Antes de começar a seguir um tutorial de agregação, você deve configurar um novo aplicativo Python. Você pode usar esse aplicativo para se conectar a um sistema do MongoDB, inserir dados de amostra no MongoDB e executar o aggregation pipeline em cada tutorial.

Dica

Para saber como instalar o driver e se conectar ao MongoDB, consulte Introdução ao PyMongo

Após instalar o driver, crie um arquivo chamado agg_tutorial.py. Cole o seguinte código neste arquivo para criar um modelo de aplicativo para os tutoriais de agregação:

from pymongo import MongoClient
# Replace the placeholder with your connection string.
uri = "<connection string>"
client = MongoClient(uri)
try:
agg_db = client["agg_tutorials_db"]
# Get a reference to relevant collections.
# ... some_coll =
# ... another_coll =
# Delete any existing documents in collections.
# ... some_coll.delete_many({})
# Insert sample data into the collection or collections.
# ... some_data = [...]
# ... some_coll.insert_many(some_data)
# Create an empty pipeline array.
pipeline = []
# Add code to create pipeline stages.
# ... pipeline.append({...})
# Run the aggregation.
# ... aggregation_result = ...
# Print the aggregation results.
for document in aggregation_result:
print(document)
finally:
client.close()

Importante

No código anterior, leia os comentários de código para localizar as seções do código que você deve modificar para o tutorial que você está seguindo.

Se você tentar executar o código sem fazer alterações, encontrará um erro de conexão.

Para cada tutorial, você deve substituir o espaço reservado da connection string de conexão pela string de conexão do seu sistema. Para saber como localizar a connection string do seu sistema, consulte Criar uma connection string.

Por exemplo, se sua string de conexão for "mongodb+srv://mongodb-example:27017", sua atribuição de string de conexão será semelhante à seguinte:

uri = "mongodb+srv://mongodb-example:27017";

Para executar o arquivo completo após modificar o modelo de um tutorial, execute o seguinte comando em seu shell:

python3 agg_tutorial.py

Após configurar a aplicação, acesse a collection orders e products adicionando o seguinte código à aplicação:

orders_coll = agg_db["orders"]
products_coll = agg_db["products"]

Exclua quaisquer dados existentes e insira dados de amostra na coleção orders como mostrado no seguinte código:

orders_coll.delete_many({})
order_data = [
{
"customer_id": "elise_smith@myemail.com",
"orderdate": datetime(2020, 5, 30, 8, 35, 52),
"product_id": "a1b2c3d4",
"value": 431.43
},
{
"customer_id": "tj@wheresmyemail.com",
"orderdate": datetime(2019, 5, 28, 19, 13, 32),
"product_id": "z9y8x7w6",
"value": 5.01
},
{
"customer_id": "oranieri@warmmail.com",
"orderdate": datetime(2020, 1, 1, 8, 25, 37),
"product_id": "ff11gg22hh33",
"value": 63.13
},
{
"customer_id": "jjones@tepidmail.com",
"orderdate": datetime(2020, 12, 26, 8, 55, 46),
"product_id": "a1b2c3d4",
"value": 429.65
}
]
orders_coll.insert_many(order_data)

Exclua quaisquer dados existentes e insira dados de amostra na coleção products como mostrado no seguinte código:

products_coll.delete_many({})
product_data = [
{
"id": "a1b2c3d4",
"name": "Asus Laptop",
"category": "ELECTRONICS",
"description": "Good value laptop for students"
},
{
"id": "z9y8x7w6",
"name": "The Day Of The Triffids",
"category": "BOOKS",
"description": "Classic post-apocalyptic novel"
},
{
"id": "ff11gg22hh33",
"name": "Morphy Richardds Food Mixer",
"category": "KITCHENWARE",
"description": "Luxury mixer turning good cakes into great"
},
{
"id": "pqr678st",
"name": "Karcher Hose Set",
"category": "GARDEN",
"description": "Hose + nosels + winder for tidy storage"
}
]
products_coll.insert_many(product_data)
1

Adicione um estágio $match que corresponda aos pedidos feitos em 2020:

pipeline.append({
"$match": {
"orderdate": {
"$gte": datetime(2020, 1, 1, 0, 0, 0),
"$lt": datetime(2021, 1, 1, 0, 0, 0)
}
}
})
2

Em seguida, adicione um estágio $lookup . O estágio $lookup une o campo product_id na collection orders ao campo id na collection products :

pipeline.append({
"$lookup": {
"from": "products",
"localField": "product_id",
"foreignField": "id",
"as": "product_mapping"
}
})
3

Em seguida, adicione dois estágios $set ao pipeline.

O primeiro estágio $set define o campo product_mapping como o primeiro elemento no objeto product_mapping criado no estágio $lookup anterior.

O segundo estágio $set cria dois novos campos, product_name e product_category, a partir dos valores no campo de objeto product_mapping :

pipeline.extend([
{
"$set": {
"product_mapping": {"$first": "$product_mapping"}
}
},
{
"$set": {
"product_name": "$product_mapping.name",
"product_category": "$product_mapping.category"
}
}
])

Dica

Como esta é uma união um-para-um, o estágio $lookup adiciona apenas um elemento de array ao documento de entrada. O pipeline usa o operador $first para recuperar os dados desse elemento.

4

Finalmente, adicione um estágio $unset . A etapa $unset remove campos desnecessários do documento:

pipeline.append({"$unset": ["_id", "product_id", "product_mapping"]})
5

Adicione o seguinte código ao final do seu aplicativo para executar a aggregation na collection orders :

aggregation_result = orders_coll.aggregate(pipeline)

Por fim, execute o seguinte comando em seu shell para iniciar seu aplicativo:

python3 agg_tutorial.py
6

O resultado agregado contém três documentos. Os documentos representam pedidos de clientes que ocorreram em 2020, com o product_name e product_category do produto pedido:

{
'customer_id': 'elise_smith@myemail.com',
'orderdate': datetime.datetime(2020, 5, 30, 8, 35, 52),
'value': 431.43,
'product_name': 'Asus Laptop',
'product_category': 'ELECTRONICS'
}
{
'customer_id': 'oranieri@warmmail.com',
'orderdate': datetime.datetime(2020, 1, 1, 8, 25, 37),
'value': 63.13,
'product_name': 'Morphy Richardds Food Mixer',
'product_category': 'KITCHENWARE'
}
{
'customer_id': 'jjones@tepidmail.com',
'orderdate': datetime.datetime(2020, 12, 26, 8, 55, 46),
'value': 429.65,
'product_name': 'Asus Laptop',
'product_category': 'ELECTRONICS'
}

O resultado consiste em documentos que contêm campos de documentos na collection orders e na collection products , unidos pela correspondência do campo product_id presente em cada documento original.

Para visualizar o código completo deste tutorial, consulte a Aplicação de Participação Um-para- Um Concluída no Github.