-
-
Notifications
You must be signed in to change notification settings - Fork 505
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
[WIP] Feature sharding #325
Changes from 5 commits
d90bba9
b6e2885
4398382
76b3528
373cecc
9257840
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -182,6 +182,11 @@ class ClassMetadataInfo implements \Doctrine\Common\Persistence\Mapping\ClassMet | |
*/ | ||
public $requireIndexes = false; | ||
|
||
/** | ||
* READ-ONLY: The fields for the query for the document collection. | ||
*/ | ||
public $queryFields = array(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Naming this |
||
|
||
/** | ||
* READ-ONLY: The name of the document class. | ||
*/ | ||
|
@@ -681,6 +686,40 @@ public function hasIndexes() | |
return $this->indexes ? true : false; | ||
} | ||
|
||
/** | ||
* Returns the custom query fields for this Document. | ||
* | ||
* @return array $fields The fields for the query. | ||
*/ | ||
public function getQueryFields() | ||
{ | ||
return $this->queryFields; | ||
} | ||
|
||
/** | ||
* Checks whether this document has custom query fields or not. | ||
* | ||
* @return boolean | ||
*/ | ||
public function hasQueryFields() | ||
{ | ||
return $this->queryFields ? true : false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. couldnt this be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed in the next commits |
||
} | ||
|
||
/** | ||
* Sets the custom query fields for this Document. | ||
* | ||
* @param array $fields Array of fields for the query. | ||
*/ | ||
public function setQueryFields($fields) | ||
{ | ||
if(!is_array($fields)) { | ||
$fields = array($fields); | ||
} | ||
|
||
$this->queryFields = $fields; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. $this->queryFields = is_array($fields) ? $fields : array($fields); Imo easier to read. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed in the next commits There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes easier, but using if () provide better performance, what is more important? |
||
} | ||
|
||
/** | ||
* Sets the change tracking policy used by this class. | ||
* | ||
|
@@ -1289,7 +1328,7 @@ public function getIdentifierValue($document) | |
if ($document instanceof Proxy && !$document->__isInitialized()) { | ||
return $document->__identifier__; | ||
} | ||
return (string) $this->reflFields[$this->identifier]->getValue($document); | ||
return $this->reflFields[$this->identifier]->getValue($document); | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -240,13 +240,17 @@ public function executeInserts(array $options = array()) | |
$upsertOptions = $options; | ||
$upsertOptions['upsert'] = true; | ||
foreach ($upserts as $oid => $data) { | ||
$criteria = array('_id' => $data[$this->cmd.'set']['_id']); | ||
unset($data[$this->cmd.'set']['_id']); | ||
$query = $this->getDocumentQuery($this->queuedInserts[$oid]); | ||
foreach ($query as $field => $value) { | ||
if (isset($data[$this->cmd.'set'][$field])) { | ||
unset($data[$this->cmd.'set'][$field]); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume this is for ensuring that shard keys aren't modified, so you'll end up replacing this with an exception? Can we simply read the shard key fields from the class metadata here? Calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes in the next update it throws exceptions |
||
// stupid php | ||
if (empty($data[$this->cmd.'set'])) { | ||
$data[$this->cmd.'set'] = new \stdClass; | ||
} | ||
$this->collection->update($criteria, $data, $upsertOptions); | ||
$this->collection->update($query, $data, $upsertOptions); | ||
} | ||
} | ||
|
||
|
@@ -263,13 +267,10 @@ public function executeInserts(array $options = array()) | |
*/ | ||
public function update($document, array $options = array()) | ||
{ | ||
$id = $this->uow->getDocumentIdentifier($document); | ||
$update = $this->pb->prepareUpdateData($document); | ||
|
||
if ( ! empty($update)) { | ||
|
||
$id = $this->class->getDatabaseIdentifierValue($id); | ||
$query = array('_id' => $id); | ||
$query = $this->getDocumentQuery($document); | ||
|
||
// Include versioning logic to set the new version value in the database | ||
// and to ensure the version has not changed since this document object instance | ||
|
@@ -320,8 +321,7 @@ public function update($document, array $options = array()) | |
*/ | ||
public function delete($document, array $options = array()) | ||
{ | ||
$id = $this->uow->getDocumentIdentifier($document); | ||
$query = array('_id' => $this->class->getDatabaseIdentifierValue($id)); | ||
$query = $this->getDocumentQuery($document); | ||
|
||
if ($this->class->isLockable) { | ||
$query[$this->class->lockField] = array($this->cmd . 'exists' => false); | ||
|
@@ -338,13 +338,12 @@ public function delete($document, array $options = array()) | |
/** | ||
* Refreshes a managed document. | ||
* | ||
* @param array $id The identifier of the document. | ||
* @param object $document The document to refresh. | ||
*/ | ||
public function refresh($id, $document) | ||
public function refresh($document) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the removal of the first argument signify a BC break, or would this public method never be called by the user. I assume perhaps it's further down the line from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO its ok. It was used only one time in the core. I don't thinks users used it. |
||
{ | ||
$class = $this->dm->getClassMetadata(get_class($document)); | ||
$data = $this->collection->findOne(array('_id' => $id)); | ||
$query = $this->getDocumentQuery($document); | ||
$data = $this->collection->findOne($query); | ||
$data = $this->hydratorFactory->hydrate($document, $data); | ||
$this->uow->setOriginalDocumentData($document, $data); | ||
} | ||
|
@@ -449,8 +448,8 @@ private function wrapCursor(BaseCursor $cursor) | |
*/ | ||
public function exists($document) | ||
{ | ||
$id = $this->class->getIdentifierObject($document); | ||
return (bool) $this->collection->findOne(array(array('_id' => $id)), array('_id')); | ||
$query = $this->getDocumentQuery($document); | ||
return (bool) $this->collection->findOne($query, array('_id')); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't the second argument be |
||
} | ||
|
||
/** | ||
|
@@ -461,10 +460,9 @@ public function exists($document) | |
*/ | ||
public function lock($document, $lockMode) | ||
{ | ||
$id = $this->uow->getDocumentIdentifier($document); | ||
$criteria = array('_id' => $this->class->getDatabaseIdentifierValue($id)); | ||
$query = $this->getDocumentQuery($document); | ||
$lockMapping = $this->class->fieldMappings[$this->class->lockField]; | ||
$this->collection->update($criteria, array($this->cmd.'set' => array($lockMapping['name'] => $lockMode))); | ||
$this->collection->update($query, array($this->cmd.'set' => array($lockMapping['name'] => $lockMode))); | ||
$this->class->reflFields[$this->class->lockField]->setValue($document, $lockMode); | ||
} | ||
|
||
|
@@ -475,10 +473,9 @@ public function lock($document, $lockMode) | |
*/ | ||
public function unlock($document) | ||
{ | ||
$id = $this->uow->getDocumentIdentifier($document); | ||
$criteria = array('_id' => $this->class->getDatabaseIdentifierValue($id)); | ||
$query = $this->getDocumentQuery($document); | ||
$lockMapping = $this->class->fieldMappings[$this->class->lockField]; | ||
$this->collection->update($criteria, array($this->cmd.'unset' => array($lockMapping['name'] => true))); | ||
$this->collection->update($query, array($this->cmd.'unset' => array($lockMapping['name'] => true))); | ||
$this->class->reflFields[$this->class->lockField]->setValue($document, null); | ||
} | ||
|
||
|
@@ -740,6 +737,40 @@ private function loadReferenceManyWithRepositoryMethod(PersistentCollection $col | |
} | ||
} | ||
|
||
/** | ||
* Gets the query for the document. | ||
* | ||
* @param mixed $document | ||
* | ||
* @return array $query | ||
*/ | ||
public function getDocumentQuery($document) | ||
{ | ||
if ($this->class->hasQueryFields()) { | ||
$changeSet = $this->uow->getDocumentChangeSet($document); | ||
$query = array(); | ||
foreach ($this->class->queryFields as $field) { | ||
if (isset($changeSet[$field])) { | ||
if (null !== $changeSet[$field][0]) { | ||
$query[$field] = $changeSet[$field][0]; | ||
} else { | ||
// upsert new document | ||
$query[$field] = $changeSet[$field][1]; | ||
} | ||
} else { | ||
$query[$field] = $this->class->getFieldValue($document, $field); | ||
} | ||
} | ||
|
||
$query = $this->prepareQuery($query); | ||
} else { | ||
$id = $this->uow->getDocumentIdentifier($document); | ||
$query = array('_id' => $this->class->getDatabaseIdentifierValue($id)); | ||
} | ||
|
||
return $query; | ||
} | ||
|
||
/** | ||
* Prepares a sort array and converts PHP property names to MongoDB field names. | ||
* | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would make more sense for this to be named
ShardKeys
, unless there is some alternative use case I'm missing. Additionally, we can consider mapping one or more fields with@ShardKey
down the line. Specifying an array of MongoDB field names (they're not property names, right?) as a class-level annotation works for now, though.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. I will change this to
@ShardKey
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The class-level annotation should be
@ShardKeys
, since users may specify one or more fields. The field-level annotation can be@ShardKey
later on.