GithubHelp home page GithubHelp logo

Comments (7)

gquemener avatar gquemener commented on July 19, 2024

Hello!

I've found a way to do it, but I'm not sure this is the correct one:

$instance->setName('bar');
$collection->updateOne(['_id' => $result->getInsertedId()], [
    '$set' => $instance->bsonSerialize()
]);
/**
 * > db.coll.findOne()
 * {
 *         "_id" : ObjectId("56a366dc046d5f0055094a91"),
 *         "__pclass" : BinData(128,"QQ=="),
 *         "name" : "bar"
 * }
 */

What do you think?

from mongo-php-library.

gquemener avatar gquemener commented on July 19, 2024

No.
After second tought, this is definitly not a good idea. bsonSerialize() is used internally by the MongoDB driver. Anyway it doesn't work with embedded document.

from mongo-php-library.

jmikola avatar jmikola commented on July 19, 2024

I believe the problem is due to your class not handling the _id field.

When inserting the instance, bsonSerialize() returns a document containing only a name field, which leaves the driver to generate an ObjectId on its own (the same that you later retrieve from the write result). When replacing the document, bsonSerialize() is again invoked and returns another document containing only name but with a different value. In my local test, that replacement does achieve the desired goal of changing the name field of the inserted document. I verified this using the shell to dump the document after the insertOne() and replaceOne() calls and there is but one document in the collection:

> db.coll.find()
{ "_id" : ObjectId("56a6a61c6118fd39a911c6e1"), "name" : "bar" }

I would suggest the following to properly handle the _id property on your class:

  • Add an $_id property on the class (or whatever you'd like the name it)
  • Ensure the property is included in bsonSerialize() if set. Unless you plan to initialize $_id to a new ObjectId (or some other value) during construction, I'd suggest you not include it in bsonSerialize() if it's null, as that will happy create a document in MongoDB with a null ID value (and naturally start throwing duplicate key exceptions after the first insertion).
  • Ensure the property is picked up in bsonUnserialize().

For example:

class A implements MongoDB\BSON\Persistable
{
    private $_id;
    private $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    public function bsonSerialize()
    {
        $data = [
            'name' => $this->name,
        ];

        if ($this->_id !== null) {
            $data['_id'] = $this->_id;
        }

        return $data;
    }

    public function bsonUnserialize(array $data)
    {
        $this->name = $data['name'];
        $this->_id = $data['_id'];
    }
}

That said, I think it would be easiest to assign a new MongoDB\BSON\ObjectID to $this->_id in your constructor and simplify bsonSerialize(). I expect this may end up being a common mistake for new users, so I will get this added to our documentation examples soon (both on PHP.net and in the upcoming library documentation for using Persistable and the other two interfaces).


That said, there is a driver problem here (below the library). The __pclass property is disappearing after the replacement is executed. Curiously, it is present when we debug the replacement document through the BSON serialization functions:

echo MongoDB\BSON\toJSON(MongoDB\BSON\fromPHP($instance));
// outputs: { "__pclass" : { "$type" : "80", "$binary" : "QQ==" }, "name" : "bar" }

Looking into the extension code, I believe we're missing PHONGO_BSON_ADD_ODS|PHONGO_BSON_ADD_CHILD_ODS flags when encoding the replacement arguments in BulkWrite.c. Those are flags we use when inserting documents, and I believe missing them for replacements was an oversight. I'll look into that and cross-reference this with a JIRA ticket on the extension soon.

Thanks for the report!

from mongo-php-library.

jmikola avatar jmikola commented on July 19, 2024

Cross-referencing:

from mongo-php-library.

gquemener avatar gquemener commented on July 19, 2024

FYI, while waiting for the fix, one must specificaly serialize the __pclass property to prevent metadata to be le lost on document update:

    public function bsonSerialize()
    {
        return [
            '_id' => $this->id,
            '__pclass' => new BSON\Binary(get_class($this), BSON\Binary::TYPE_USER_DEFINED),
            //... whatever other fields you want to persist
        ];
    }

from mongo-php-library.

jmikola avatar jmikola commented on July 19, 2024

FYI: PHPC-550 has been merged and is slated for a 1.1.3 release this week.

from mongo-php-library.

jmikola avatar jmikola commented on July 19, 2024

1.1.3 has been released, so I think this can be closed. Feel free to follow up if the issue persists.

from mongo-php-library.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.