public function upsert($document, $parentPath = null)
    {
        $class     = $this->dm->getClassMetadata(get_class($document));
        $changeset = $this->uow->getDocumentChangeSet($document);

        if (!$class->isEmbeddedDocument) {
            $qb         = $this->dm->createQueryBuilder($class->name);
            $identifier = $class->createIdentifier($document);

            $qb->update();
            $qb->setIdentifier($identifier);
        } elseif ($parentPath === null) {
            throw new \InvalidArgumentException;
        }

        foreach ($changeset as $attributeName => $change) {
            if ($class->isIdentifier($attributeName)) {
                continue;
            }

            list($old, $new) = $change;

            $mapping            = $class->getPropertyMetadata($attributeName);
            $discriminatorValue = null;

            if ($mapping->embedded && $mapping->isOne()) {
                $embeddedClassName  = get_class($new);
                $embeddedClass      = $this->dm->getClassMetadata($embeddedClassName);
                $discriminatorValue = $embeddedClass->getEmbeddedDiscriminatorValue($mapping, $new);
                //@Many will set discriminator in updatePath
            }

            if ($class->isEmbeddedDocument) {
                $path = $parentPath->map($attributeName, $discriminatorValue);
            } else {
                $path = $qb->attr($attributeName, $discriminatorValue);
            }

            $this->updatePath($path, $old, $new, true);
        }

        // add discriminator if the class has one
        if ($class->discriminatorAttribute !== null) {
            if ($class->isEmbeddedDocument) {
                $path = $parentPath->map($class->discriminatorAttribute);
            } else {
                $path = $qb->attr($class->discriminatorAttribute);
            }

            $path->set(
                $class->discriminatorValue !== null
                    ? $class->discriminatorValue
                    : $class->name
            );
        }

        if ($this->class->isVersioned) {
            // Set the initial version. Only supported on top-level documents.

            $versionMapping = $this->class->getPropertyMetadata($this->class->versionAttribute);
            $nextVersion    = null;

            if ($versionMapping->type === Type::INT) {
                $nextVersion = max(1, (int)$versionMapping->getValue($document));
            } elseif ($versionMapping->isDateType()) {
                $nextVersion = new \DateTime();
            }

            $nextVersion = $versionMapping->getType()->convertToDatabaseValue($nextVersion);
            $versionMapping->setValue($document, $nextVersion);

            $qb->attr($versionMapping->name)->set($nextVersion);
        }

        //DynamoDB will upsert even if we only pass the id conditional with no UpdateExpression

        if (!$class->isEmbeddedDocument) {
            $qb->getQuery()->execute();
        }
    }