Модель фильтрации Mongoengine / MongoDB по наличию ключа в поле «Словарь» - PullRequest
0 голосов
/ 28 мая 2019

Я строю модель данных, используя Mongoengine для хранения метаданных, в данном случае, файлов электронной почты. Очень урезанная модель, в которой есть только поле, относящееся к моей проблеме:

class Email(Document):
    headers = DictField()

Словарь заголовков будет содержать извлеченные данные заголовков из электронных писем, которые работают в отношениях ключ-значение.

В этих данных заголовка, которые я знаю, иногда будет присутствовать заголовок с именем (и ключом словаря): x-mailer (все ключи заголовка автоматически в нижнем регистре). Я построил простой запрос, чтобы увидеть, содержит ли заголовок этот ключ, например:

xmailer_emails = Email.objects.filter(headers__exists='x-mailer')

Тем не менее, результаты этого не содержат все записей в коллекции email, но содержит немало, которые не имеют x-mailer в качестве ключа в headers толковый словарь. Вот некоторый код, который я использовал для проверки полученных данных:

xmailer_emails = Email.objects.filter(headers__exists='x-mailer'))
log(xmailer_emails._query)

log('Total email count: ' + str(Email.objects.count()))
log('X-Mailer email acount: ' + str(xmailer_emails.count()))

no_xmailer = len([e for e in xmailer_emails if 'x-mailer' not in e.headers])
log('Filtered no x-mailer count: ' + str(no_xmailer))

has_xmailer = len([e for e in xmailer_emails if 'x-mailer' in e.headers])
log('Filtered has x-mailer count: ' + str(has_xmailer))

Вот вывод, который я получаю:

[21:32:54 05/27/19] {'headers': {'$exists': 'x-mailer'}}
[21:32:54 05/27/19] Total email count: 86
[21:32:54 05/27/19] X-Mailer email count: 79
[21:32:54 05/27/19] Filtered no x-mailer count: 55
[21:32:54 05/27/19] Filtered has x-mailer count: 24

Таким образом, хотя в коллекции 86 записей, 79 из них возвращаются на фильтр для x-mailer в headers. Отфильтровывая только 24 из них, в словаре есть значение ключа. Кажется, я что-то делаю не так, но не знаю, что.

Вот краткий дамп нескольких предметов, которые он также извлекает, которые не содержат ключ x-mailer, это ключи:

dict_keys(['x-receiver', 'to', 'mime-version', 'received', 'x-priority', 'x-sender', 'date', 'content-type', 'message-id', 'subject', 'x-riferimento-message-id', 'from'])
dict_keys(['content-type', 'mime-version'])
dict_keys(['x-wum-to', 'date', 'x-uidl', 'message-id', 'in-reply-to', 'x-wum-replyto', 'x-message-delivery', 'mime-version', 'received', 'x-savecopy', 'authentication-results', 'x-wum-nature', 'x-account-key', 'x-wum-from', 'message-context', 'x-originalarrivaltime', 'x-me-spamrating', 'x-me-spamlevel', 'to', 'x-dkim-result', 'x-mozilla-status', 'x-mozilla-status2', 'references', 'x-auth-result', 'x-store-info', 'return-path', 'x-message-info', 'x-sid-pra', 'x-message-status', 'sender', 'x-wum-cci', 'content-type', 'reply-to', 'subject', 'from'])
dict_keys(['x-ms-has-attach', 'to', 'mime-version', 'received', 'thread-topic', 'x-auto-response-suppress', 'x-ms-exchange-organization-authsource', 'content-language', 'content-type', 'date', 'subject', 'message-id', 'thread-index', 'reply-to', 'from'])

Я не могу понять, что происходит, в то время как оператор exists работает, он также включает несоответствующие документы, но не все в коллекции.

Я также поднимал этот вопрос как проблему в хранилище mongoengine без ответа (кроме связанной проблемы SO для оператора exists): https://github.com/MongoEngine/mongoengine/issues/2059

1 Ответ

1 голос
/ 28 мая 2019

Запрос Pymongo, который вам действительно нужно выполнить, следующий:

c.find({'headers.x-mailer': {'$exists': True}})

Если у вас есть простые ключи (например, «xmailer» вместо «x-mailer»), вы можете добиться этого в mongoengine с помощью: Email.objects.filter(headers__xmailer__exists=True))

Но вы можете достичь этого, используя оператор raw :

Email.objects.filter(__raw__={'headers.x-mailer': {'$exists': True}})

...