Вставить поле только если не ноль - PullRequest
0 голосов
/ 05 ноября 2019

У меня есть документ Mongodb, который я хочу обновить с некоторой информацией, которую я получаю из формы. Исходный документ в Mongodb содержит следующие данные:

{"id":1, "name": "James", "surname1": "Adams"} [id is univoque]

Информация, полученная из формы, следующая (ее структура всегда одинакова):

id = 1
name = "James"
surname1 = "Adams"
surname2 = ""
synced = 1

Для обновленияэтот документ из коллекции foo, я делаю следующую операцию:

mongoClient = MongoClient('localhost:27017').db
mongoClient["foo"].update({"id" : id}, {"$set" : {"name" : name, "surname1" : surname1, "surname2" : surname2, "synced" : synced}})

Это создаст пустое поле для surname2. И вот мой вопрос: какой самый питонный способ вставить в Mongodb только те поля, которые не пусты? Может ли это быть сделано с внутренней логикой Mongodb или это может быть выполнено только с некоторыми проверками Python входных данных?

Ответы [ 2 ]

1 голос
/ 05 ноября 2019

Хитрость заключается в pop () элементах из записи перед загрузкой. Попробуйте это в качестве примера:

from pymongo import MongoClient

mongoClient = MongoClient('localhost:27017').db

# Setup some test data
for i in range(3):
    mongoClient["foo"].insert({"id": i, "name": "James", "surname1": "Adams"})

# Simulate your incoming record
record = {"id": 1, "name": "James", "surname1": "Adams", "surname2": "", "synced": 1}

# Remove any empty items    
for k, v in list(record.items()):
    if v == '' or v is None:
        record.pop(k)

mongoClient["foo"].update({"id": record['id']}, {"$set": record})

for item in mongoClient["foo"].find({}, {"_id": 0}):
    print(item)

Результат:

{'id': 0, 'name': 'James', 'surname1': 'Adams'}
{'id': 1, 'name': 'James', 'surname1': 'Adams', 'synced': 1}
{'id': 2, 'name': 'James', 'surname1': 'Adams'}
0 голосов
/ 06 ноября 2019

Оптовые обновления документов (где заменяется весь документ базы данных) стоят дорого. Если у вас есть способ обнаружить изменения в документе в вашем приложении, вы можете предоставить базе данных целевые обновления. Первоначально этот вопрос заключался в том, как обновить документы в базе данных так, чтобы пустые или пустые поля были удалены, чтобы уменьшить общий размер документа. Предположительно это должно повысить производительность и уменьшить потребление дискового пространства. Обе замечательные цели. Но вот в чем дело - мы не только хотим иметь хорошо структурированные документы на диске, но и должны учитывать, как мы управляем этими данными. Выполнение оптовых обновлений и замена всего документа, безусловно, облегчает разработку клиента, но накладывает нагрузку на ядро ​​базы данных. MongoDB поддерживает документы объемом до 16 МБ, поэтому, чем больше размер документа, тем больше будет эффект от замены документа оптом. Целевые обновления предпочтительнее, но как нам это сделать? Как мы узнаем, какие поля отличаются между моим входящим документом и что находится в базе данных? На самом деле это скорее философский вопрос. Мы можем запросить базу данных и сравнить с входящим документом, но опять же, это влияет на базу данных. Но учтите это - для любого документа, который мы хотим обновить, мы должны были изначально получить его из базы данных - верно? В противном случае это новый документ (вставка, а не обновление). Если мы сделали это из базы данных, то у нас есть возможность отслеживать, какие изменения мы внесли в документ. Если это так, то наши входящие данные могут быть не более чем набором изменений, а не самим документом. Опять же, это философия, а не наука. Итак, рассмотрим сценарий, в котором входящие данные являются изменениями, а не фактическим документом. Мы могли бы создать инструкции для отмены полей, где они были удалены, и для обновления целевых полей, где они изменены, но остаются. Первоначальный вопрос был о том, как создать «питоническое» решение для удаления пустых полей, но этот вопрос действительно стоит на поверхности более глубокой проблемы отслеживания изменений.

...