0

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:

  1. Neither name nor domain (I use other fields not shown to define the document)
  2. Either name or domain, but not both
  3. 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?

Joe Walsh
  • 396
  • 3
  • 6
  • 1
    Wow this makes my head hurt! If you really want to avoid the round trips to the your api and database, have you looked at graphene for python? They have docs that support both Django and Flask. [Graphene Graphql](http://graphene-python.org/) – Joseph Vargas May 24 '18 at 05:41
  • Thanks for the suggestion -- I'll give it a try. – Joe Walsh Feb 25 '19 at 00:30

0 Answers0