Here's what I want to do:
Toss a new document at the DB and have it throw back an updated existing document if there's a match (based on some or all of the uniqueness constraints).
I have a collection of companies:
class Company(DynamicDocument):
name = StringField(unique=True, sparse=True)
domain = StringField(unique=True, sparse=True)
...
In some cases, the incoming information contains:
- Neither name nor domain (I use other fields not shown to define the document)
- Either name or domain, but not both
- Both domain and name
Here's the behavior I want:
if not name and not domain:
return document(...).save()
elif name or domain:
# check for existing match to either name or domain
if existing doc:
return document.modify(...)
else:
return document(...).save()
(I think) I want to add a custom save method to avoid writing a module to validate against each unique index before trying to save a document. I have another 8 collections with their own uniqueness constraints and I want to abstract this solution as much as possible.
To that end, I tried some rather complicated stuff that felt wrong while I was writing it and works only when scenario 3 has 2 exact matches (I add this messy code just to prove I tried):
@classmethod
def csave(cls, **kwargs):
d = cls(**kwargs)
try:
doc = d.save()
except NotUniqueError:
# get unique indexes for the collection
indexes = d._unique_with_indexes()
# get the specific fields
fields = [f['fields'][0][0] for f in indexes if f.get('unique')]
# build a search dictionary
matches = {k: v for k, v in kwargs.items() if k in fields}
doc = cls.objects(**matches).first()
return doc
else:
return doc
As I went down the rabbit hole trying to make this mess functional, I realized there must be a better way of doing what I want to do.
Any ideas for a cleaner way to make this happen?