Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

for manual document upserting #106

Closed
wants to merge 19 commits into from
Closed

for manual document upserting #106

wants to merge 19 commits into from

Conversation

horrower
Copy link
Contributor

$sMongoID = md5('555' . 'www.apple.com');

$doc = new Document($collection);
$doc->setId($sMongoID);
$doc->set('manufacturer', 'apple.com');
$doc->set('name', 'iPad');
$doc->set('cap', '32GB');

// document created
$doc->save();

unset($doc);

$sMongoID = md5('555' . 'www.apple.com');

$doc = new Document($collection);
// creating document wit SAME id
$doc->setId($sMongoID);
// set color
$doc->set('color','white');

$doc->save() ; // it will update document, set color


$sMongoID = md5('555' . 'www.apple.com');

$doc = new Document($collection);
$doc->setId($sMongoID);
$doc->set('manufacturer', 'apple.com');
$doc->set('name', 'iPad');
$doc->set('cap', '32GB');

// document created
$doc->save();

unset($doc);

$sMongoID = md5('555' . 'www.apple.com');


$doc = new Document($collection);
// creating document wit SAME id
$doc->setId($sMongoID);
// set color
$doc->set('color','white');

$doc->save() ; // it will update document, set color
You can use '\Modules\Models\Collections\Users' instead of "users" in class and it will use your collection and your getDocumentClassName for hydrate returned related objects
in unit of work
+ autoformatter
test
@sokil
Copy link
Owner

sokil commented Aug 13, 2015

I don't understand why you are trying to create document twice. In ORM document is an object representation of some data in database. So to update document you need to load document from database. But you are trying to upsert document instead of update.

Correct use case is:

<?php

// Create document
$sMongoID = md5('555' . 'www.apple.com');
$doc = $collection->createDocument()
    ->setId($sMongoID)
    ->set('manufacturer', 'apple.com')
    ->set('name', 'iPad')
    ->set('cap', '32GB')
    ->save();

unset($doc);

// update document
$doc = $collection
    ->getDocument($sMongoID);
    ->set('color','white') 
    ->save();

Document::setId() marks field as changed, and document became unstored with defined id:

<?php
class Document 
{
    public function isStored()
    {
        return $this->get('_id') && !$this->isModified('_id');
    }
}

And unstored document with defined id will be inserted, and of course fails with duplicale key. So if you really want to update document in your strange way, you need to define _id, but without mark it as modified. There is method for that: Document::defineId(). So you can update document in that way:

<?php
// Create document
$sMongoID = md5('555' . 'www.apple.com');
$doc = $collection->createDocument()
    ->defineId($sMongoID)
    ->set('color','white') 
    ->save();

And persistence will work well. But it's weird.

PS. Your pull request is not PSR compatible, and it broke tests for php 5.3. Also thank you for idea about events in unit of work, i'v forget about them. They will be added soon

@horrower
Copy link
Contributor Author

Because when you parse 30+ sites with python crawlers, why do you need to do additional Select from DB while you can just do upsert?

I'v made fork from your repo, there is many changes above your project, you can check it. For example, documentEvents in Persist (with upsert too)

@sokil
Copy link
Owner

sokil commented Aug 13, 2015

So why you dont use directly $collection->update() with upsert? If you really need upsert in entity, use Document::defineId(). But imho this can add data inconsisted state, because some busines logic inside Document may require all fields.

For example you can add beforeSave event which set one field relatively to value of another field.

But at last i understand want you want and i will think how to do that in more clear way than setting upsert flag. i'm trying to hide all mongo options by clean interface.

By the way doctrine's mongo add upsert when id set, maybe it is better solution than setId/defineId in this lib:

http://doctrine-mongodb-odm.readthedocs.org/en/latest/reference/upserting-documents.html

@sokil
Copy link
Owner

sokil commented Aug 13, 2015

#107
#108

for not creating collection anytime on getRelated called
@horrower
Copy link
Contributor Author

$collection->update() with upsert

Because we need it in batch..

merge from Sokil last master to Horrower branch
Prevents mongo error: could not set and unset field at the same time 
           if Document have Set and Unset fields at the samae time
@sokil
Copy link
Owner

sokil commented Sep 27, 2015

Impelmented batch processing of operations instad of documents:

<?php
$collection
    ->createBatchUpdate()
    ->update(
        array('a' => 1),
        array('$set' => array('b' => 'updated1')),
        $multiple,
        $upsert
    )
    ->execute('majority');

@sokil sokil closed this Sep 27, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants