0

I'm having a hard time struggling how to find out how to upsert in MongoDB using mongoengine.

My current inserting code looks like this:

for issue in data['issues']:

    doc = Issue(
        key=issue['key'],
        title=issue["fields"]["summary"],
        type=issue["fields"]["issuetype"]["name"],
        status=issue["fields"]["status"]["name"],
        assignee=issue["fields"]["assignee"]["displayName"] if issue["fields"]["assignee"] else None,
        labels=issue["fields"]["labels"],
        components=[c['name'] for c in issue["fields"]["components"]],
        storypoints=int(issue["fields"]["customfield_10002"]) if issue["fields"]["customfield_10002"] else 0,
        sprints=[x['name'] for x in sprint_dict] if sprint_dict != None else None,
        updated_at=datetime.utcnow(),
        created=issue["fields"]["created"]
    )
    
    doc.save()

This of course only saves, but I've tried so many variants of update with upsert=True etc that I found, and none of them worked.

3 Answers 3

0

It's here https://docs.mongoengine.org/apireference.html#mongoengine.queryset.QuerySet.update_one

Assuming the unique Id is key and you want to overwrite all fields on update, it must be

Issue.objects(key=issue['key']).update_one(upsert=True,
    set__key=issue['key']
    set__title=issue["fields"]["summary"],
    set__type=issue["fields"]["issuetype"]["name"],
    set__status=issue["fields"]["status"]["name"],
    set__assignee=issue["fields"]["assignee"]["displayName"] if issue["fields"]["assignee"] else None,
    set__labels=issue["fields"]["labels"],
    set__components=[c['name'] for c in issue["fields"]["components"]],
    set__storypoints=int(issue["fields"]["customfield_10002"]) if issue["fields"]["customfield_10002"] else 0,
    set__sprints=[x['name'] for x in sprint_dict] if sprint_dict != None else None,
    set__updated_at=datetime.utcnow(),
    set__created=issue["fields"]["created"]
)

components and sprints seem to be lists, so if you want to add to the lists rather than overwrite them, you should use

push_all__components=[c['name'] for c in issue["fields"]["components"]]
push_all__sprints=[x['name'] for x in sprint_dict] if sprint_dict != None else []

List of all modifiers is here: https://docs.mongoengine.org/apireference.html#mongoengine.queryset.QuerySet.update_one pick the ones that suit your idea of upserting.

Sign up to request clarification or add additional context in comments.

Comments

0

I believe what you are doing is already correct. The documentation of the .save() method says:

Save the Document to the database. If the document already exists, it will be updated, otherwise it will be created. Returns the saved object instance.

Which is the definition of an upsert. Looking at the source code, it seems that it actually does not use mongo's upsert operation, but it achieves the same.

Comments

0

To upsert the Issue document in the code you provided, you can use the update_one() method with the upsert=True option after creating the doc object. Here's an example:

from mongoengine import connect, Document, StringField, ListField, IntField, DateTimeField

# define the Issue document
class Issue(Document):
    key = StringField(required=True, unique=True)
    title = StringField(required=True)
    type = StringField(required=True)
    status = StringField(required=True)
    assignee = StringField()
    labels = ListField(StringField())
    components = ListField(StringField())
    storypoints = IntField(default=0)
    sprints = ListField(StringField())
    updated_at = DateTimeField()
    created = DateTimeField()

# connect to MongoDB
connect('mydb')

# iterate over the issues in the data object
for issue in data['issues']:
    # create an Issue object for each issue
    doc = Issue(
        key=issue['key'],
        title=issue["fields"]["summary"],
        type=issue["fields"]["issuetype"]["name"],
        status=issue["fields"]["status"]["name"],
        assignee=issue["fields"]["assignee"]["displayName"] if issue["fields"]["assignee"] else None,
        labels=issue["fields"]["labels"],
        components=[c['name'] for c in issue["fields"]["components"]],
        storypoints=int(issue["fields"]["customfield_10002"]) if issue["fields"]["customfield_10002"] else 0,
        sprints=[x['name'] for x in sprint_dict] if sprint_dict != None else None,
        updated_at=datetime.utcnow(),
        created=issue["fields"]["created"]
    )

    # upsert the document in the database
    doc.update_one(set__key=doc.key, upsert=True)

In this example, we define the Issue document and connect to the MongoDB database. We then iterate over the issues in the data object, creating an Issue object for each issue. After creating the doc object, we use the update_one() method with the set__key=doc.key parameter to update the document with the specified key, or insert it if it doesn't exist (upsert=True). This will ensure that each document in the database corresponds to a unique issue key.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.