Eu tenho uma base e preciso dentro de um cliente que possui 17 MM de registros selecionar um range de 5 mil contatos, que atenda uma query dentro dessa collection.
Estou utilizando o MongoEngine e PyMongo com CursorCollection e não consigo interagir sobre o primeiro registro desse subset. Ao tentar executar o banco de dados abenda e não ocorre a interação.
Coloquei o mongo DB para rodar em uma máquina na AWS t3.xlarge e ainda assim ao executar essa query ela não roda.
cursor = Contact._get_collection().find(query, {
'id': 1
}).hint([('customer_id', 1), ('tag_list', 1), ('status', 1),
('opt_out', 1)
]).batch_size(5000).limit(5000)[1100001: 1149999]
Eu pretendo utilizar essa query para interar e fazer um updateMany, conforme rotina abaixo:
update_exec = {
'$push': {
'campaigns': {'id': campaign_id, 'was_sent': False, 'type':
campaign_type}
}
}
for c in cursor:
contact = Contact._from_son(c)
bulk_operations.append(
UpdateOne({
'_id':
contact.id,
'campaigns': {
'$not':{
'$elemMatch':{
'id': campaign_id,
}
}
}
}, update_exec)
)
results = Contact._get_collection().bulk_write(bulk_operations, ordered=False)
A minha classe Contact está abaixo descrita para que vejam como ela foi estruturada:
# Create your models here.
class Contact(mongo.DynamicDocument):
STATUS_CHOICES = (('ok', _('Ativo')),
('mx', _('Falha na entrega')),
('invalid_domain', _('Dominio inválido')),
('inexistent_address', _('E-mail não existe')),
('mailbox_full', _('Caixa cheia')),
('size_limit', _('Limite da mensagem excedido')),
('mail_loop', _('E-mail em loop')),
('spam', _('Spam')),
('unknown', _('Erro desconhecido')),
('complaint', _('Reclamação')),
('abuse', _('Denúncia de Abuse')),
('smsfail', _('Falha na Entrega de SMS')),
('whatsappfail', _('Falha na Entrega de WhatsApp')))
customer_id = mongo.IntField(verbose_name=_(u'Cliente'),
unique_with='email')
name = mongo.StringField(max_length=255, verbose_name=_(u'Nome'))
email = mongo.EmailField(verbose_name=_(u'E-mail'))
campaigns = mongo.ListField(mongo.DictField(),
verbose_name=_(u'Campanhas que o usuário participou'))
customs = mongo.ListField(mongo.DictField(),
verbose_name=_(u'Campos customizados do cliente'))
status = mongo.StringField(choices=STATUS_CHOICES, default='ok',
max_length='10', verbose_name=_(u'Status do E-mail'))
date_created = mongo.DateTimeField(verbose_name=_(u'Criado em'))
last_updated = mongo.DateTimeField(verbose_name=_(u'Última atualização em'))
tag_list = mongo.ListField(mongo.StringField(),
verbose_name=_(u'Listas que o contato faz parte'))
meta = {
'index_background': True,
'index_drop_dups': True,
'indexes': [
('customer_id', 'tag_list', 'status', 'opt_out'),
('customer_id', 'tag_list', 'status'),
('customer_id', 'tag_list', 'opt_out'),
('customer_id', 'customs.k', 'customs.v', 'status', 'opt_out')
],
}
class Meta:
using = 'mongodb'
verbose_name = _(u'Contato')
verbose_name_plural = _(u'Contatos')
Eu tentei já utilizar skip and limit e inicialmente atende, mas quando aumenta a posicao inicial mais para meio do intervalo, a query fica realmente lenta.
Tentei outras abordagens utilizando intervalo ao final da query somente com o limit, mas também não funcionou.
Agradeço de coração a ajuda dos amigos!