Update a document and return it
public findAndModify ( array $query, array $update = null, array $fields = null, array $options = [] ) : array | ||
$query | array | The query criteria to search for. |
$update | array | The update criteria. |
$fields | array | Optionally only return these fields. |
$options | array | An array of options to apply, such as remove the match document from the DB and return it. |
Результат | array | Returns the original document, or the modified document when new is set. |
/** * Lookup a specific cache entry * * Optionally, increment the hit counter when loading the cache entry * * @param integer $id * @param boolean $incrementHitCounter = false * @return array | FALSE */ private function get($id, $incrementHitCounter = false) { if ($incrementHitCounter === true) { return $this->_collection->findAndModify(array('_id' => $id), array('$inc' => array('hits' => 1))); } else { return $this->_collection->findOne(array('_id' => $id)); } }
/** * Get a non qr message from the queue. * * @param array $query in same format as \MongoCollection::find() where top level fields do not contain operators. * Lower level fields can however. eg: valid {a: {$gt: 1}, "b.c": 3}, invalid {$and: [{...}, {...}]} * @param int $runningResetDuration second duration the message can stay unacked before it resets and can be retreived again. * @param int $waitDurationInMillis millisecond duration to wait for a message. * @param int $pollDurationInMillis millisecond duration to wait between polls. * * @return array|null the message or null if one is not found * * @throws \InvalidArgumentException $runningResetDuration, $waitDurationInMillis or $pollDurationInMillis was not an int * @throws \InvalidArgumentException key in $query was not a string */ public function get(array $query, $runningResetDuration, $waitDurationInMillis = 3000, $pollDurationInMillis = 200) { if (!is_int($runningResetDuration)) { throw new \InvalidArgumentException('$runningResetDuration was not an int'); } if (!is_int($waitDurationInMillis)) { throw new \InvalidArgumentException('$waitDurationInMillis was not an int'); } if (!is_int($pollDurationInMillis)) { throw new \InvalidArgumentException('$pollDurationInMillis was not an int'); } if ($pollDurationInMillis < 0) { $pollDurationInMillis = 0; } //reset stuck messages $this->_collection->update(array('qr' => true, 'rTs' => array('$lte' => new \MongoDate())), array('$set' => array('qr' => false)), array('multiple' => true)); $completeQuery = array('qr' => false); foreach ($query as $key => $value) { if (!is_string($key)) { throw new \InvalidArgumentException('key in $query was not a string'); } $completeQuery["payload.{$key}"] = $value; } $completeQuery['qTs'] = array('$lte' => new \MongoDate()); $rTs = time() + $runningResetDuration; //ints overflow to floats if (!is_int($rTs)) { $rTs = $runningResetDuration > 0 ? self::MONGO_INT32_MAX : 0; } $update = array('$set' => array('rTs' => new \MongoDate($rTs), 'qr' => true)); $fields = array('payload' => 1); $options = array('sort' => array('py' => 1, 'ts' => 1)); //ints overflow to floats, should be fine $end = microtime(true) + $waitDurationInMillis / 1000.0; $sleepTime = $pollDurationInMillis * 1000; //ints overflow to floats and already checked $pollDurationInMillis was positive if (!is_int($sleepTime)) { //ignore since testing a giant sleep takes too long //@codeCoverageIgnoreStart $sleepTime = PHP_INT_MAX; } //@codeCoverageIgnoreEnd while (true) { $message = $this->_collection->findAndModify($completeQuery, $update, $fields, $options); //checking if _id exist because findAndModify doesnt seem to return null when it can't match the query on older mongo extension if ($message !== null && array_key_exists('_id', $message)) { //id on left of union operator so a possible id in payload doesnt wipe it out the generated one return array('id' => $message['_id']) + $message['payload']; } if (microtime(true) >= $end) { return null; } usleep($sleepTime); } //ignore since always return from the function from the while loop //@codeCoverageIgnoreStart }
/** * 若投票成功,返回投票后的投票值,若失败,返回 null * * @param \MongoCollection $collection * @param array $query * @param int $uid * @param int $value * @return int|null * @throws InvalidArgumentException */ public static function vote(\MongoCollection $collection, array $query, $uid, $value) { if ($value !== 1 && $value !== -1) { throw new InvalidArgumentException('value', 'value_invalid'); } if (!Validator::int()->validate($uid)) { throw new InvalidArgumentException('uid', 'type_invalid'); } $value = (int) $value; $result = $collection->findAndModify(array_merge($query, ['votes.' . strval(intval($uid)) => ['$exists' => false]]), ['$set' => ['votes' . strval(intval($uid)) => $value], '$inc' => ['voting' => $value]], ['voting' => 1], ['new' => true]); if ($result === null) { // vote failed return null; } else { // vote succeeded return $result['voting']; } }
/** */ public function read($id) { /* Check for session existence. Unfortunately needed because * we need findAndModify() for its atomicity for locking, but this * atomicity means we can't tell the difference between a * non-existent session and a locked session. */ $exists = $this->_db->count(array(self::SID => $id)); $exist_check = false; $i = 0; /* Set a maximum unlocking time, to prevent runaway PHP processes. */ $max = ini_get('max_execution_time') * 10; while (true) { $data = array(self::LOCK => time(), self::SID => $id); /* This call will either create the session if it doesn't exist, * or will update the current session and lock it if not already * locked. If a session exists, and is locked, $res will contain * an empty set and we need to sleep and wait for lock to be * removed. */ $res = $this->_db->findAndModify(array(self::SID => $id, self::LOCK => array('$exists' => $exist_check)), array($data), array(self::DATA => true), array('update' => array('$set' => $data), 'upsert' => !$exists)); if (!$exists || isset($res[self::DATA])) { break; } /* After a second, check the timestamp to determine if this is * a stale session. This can prevent long waits on a busted PHP * process. */ if ($i == 10) { $res = $this->_db->findOne(array(self::SID => $id), array(self::LOCK => true)); $max = isset($res[self::LOCK]) ? (time() - $res[self::LOCK]) * 10 : $i; } if (++$i >= $max) { $exist_check = true; } else { /* Sleep for 0.1 second before trying again. */ usleep(100000); } } $this->_locked = $id; return isset($res[self::DATA]) ? $res[self::DATA]->bin : ''; }
<?php require 'VT/config.php'; $counter = 0; $m = new MongoClient(); $db = $m->selectDB($mongo_db); $collection = new MongoCollection($db, $mongo_collection); $cursor = $collection->find(); if ($crits_on == "true") { foreach ($cursor as $array) { $url = $crits_url . "/api/v1/samples/?c-md5=" . $array['md5'] . "&username="******"&api_key=" . $crits_api_key . "®ex=1"; $result2 = file_get_contents($url, false); $thejson = json_decode($result2, true); if ($thejson['meta']['total_count'] == 1) { $retval = $collection->findAndModify(array("id" => $array['id']), array('$set' => array('crits' => "true"))); $counter++; } } echo "Found " . $counter . " Samples in Crits"; } else { echo "Crits config is set to False"; }
<? require('config.php'); $theId = intval($_POST['archId']); $m = new MongoClient("mongodb://".$mongo_server_host.":".$mongo_server_port); $db = $m->selectDB($mongo_db); $collection = new MongoCollection($db, $mongo_collection); $retval = $collection->findAndModify( array("id" => $theId), array('$set' => array('archive' => null)) ); $id_check = array('id' => $theId); $cursor = $collection->find($id_check); foreach ($cursor as $array) { if($array['archive'] == null) { echo "unarchived"; } else { echo "fail"; } } ?>
/** * {@inheritdoc} */ protected function addToTransaction($record = null, $id = null, $extras = null, $rollback = false, $continue = false, $single = false) { $ssFilters = ArrayUtils::get($extras, 'ss_filters'); $fields = ArrayUtils::get($extras, ApiOptions::FIELDS); $requireMore = ArrayUtils::get($extras, 'require_more'); $updates = ArrayUtils::get($extras, 'updates'); // convert to native format $id = static::idToMongoId($id); $fieldArray = $rollback ? null : static::buildFieldArray($fields); $out = []; switch ($this->getAction()) { case Verbs::POST: $parsed = $this->parseRecord($record, $this->tableFieldsInfo, $ssFilters); if (empty($parsed)) { throw new BadRequestException('No valid fields were found in record.'); } if (!$continue && !$rollback && !$single) { return parent::addToTransaction($parsed, $id); } $result = $this->collection->insert($parsed); static::processResult($result); $out = static::cleanRecord($parsed, $fields, static::DEFAULT_ID_FIELD); if ($rollback) { $this->addToRollback(static::recordAsId($parsed, static::DEFAULT_ID_FIELD)); } break; case Verbs::PUT: if (!empty($updates)) { $parsed = $this->parseRecord($updates, $this->tableFieldsInfo, $ssFilters, true); $updates = $parsed; } else { $parsed = $this->parseRecord($record, $this->tableFieldsInfo, $ssFilters, true); } if (empty($parsed)) { throw new BadRequestException('No valid fields were found in record.'); } // only update/patch by ids can use batching if (!$continue && !$rollback && !$single && !empty($updates)) { return parent::addToTransaction(null, $id); } $options = ['new' => !$rollback]; if (empty($updates)) { $out = static::cleanRecord($record, $fields, static::DEFAULT_ID_FIELD); static::removeIds($parsed, static::DEFAULT_ID_FIELD); $updates = $parsed; } else { $record = $updates; $record[static::DEFAULT_ID_FIELD] = $id; $out = static::cleanRecord($record, $fields, static::DEFAULT_ID_FIELD); } // simple update overwrite existing record $filter = [static::DEFAULT_ID_FIELD => $id]; $criteria = $this->buildCriteriaArray($filter, null, $ssFilters); $result = $this->collection->findAndModify($criteria, $updates, $fieldArray, $options); if (empty($result)) { throw new NotFoundException("Record with id '{$id}' not found."); } if ($rollback) { $this->addToRollback($result); } else { $out = static::fromMongoObjects($result); } break; case Verbs::MERGE: case Verbs::PATCH: if (!empty($updates)) { $parsed = $this->parseRecord($updates, $this->tableFieldsInfo, $ssFilters, true); $updates = $parsed; } else { $parsed = $this->parseRecord($record, $this->tableFieldsInfo, $ssFilters, true); } if (empty($parsed)) { throw new BadRequestException('No valid fields were found in record.'); } // only update/patch by ids can use batching if (!$continue && !$rollback && !$single && !empty($updates)) { return parent::addToTransaction(null, $id); } $options = ['new' => !$rollback]; if (empty($updates)) { static::removeIds($parsed, static::DEFAULT_ID_FIELD); $updates = $parsed; } $updates = ['$set' => $updates]; // simple merge with existing record $filter = [static::DEFAULT_ID_FIELD => $id]; $criteria = $this->buildCriteriaArray($filter, null, $ssFilters); $result = $this->collection->findAndModify($criteria, $updates, $fieldArray, $options); if (empty($result)) { throw new NotFoundException("Record with id '{$id}' not found."); } if ($rollback) { $this->addToRollback($result); // need to retrieve the full record here if ($requireMore) { $result = $this->collection->findOne($criteria, $fieldArray); } else { $result = [static::DEFAULT_ID_FIELD => $id]; } } $out = static::fromMongoObjects($result); break; case Verbs::DELETE: if (!$continue && !$rollback && !$single) { return parent::addToTransaction(null, $id); } $options = ['remove' => true]; // simple delete existing record $filter = [static::DEFAULT_ID_FIELD => $id]; $criteria = $this->buildCriteriaArray($filter, null, $ssFilters); $result = $this->collection->findAndModify($criteria, null, $fieldArray, $options); if (empty($result)) { throw new NotFoundException("Record with id '{$id}' not found."); } if ($rollback) { $this->addToRollback($result); $out = static::cleanRecord($record, $fields, static::DEFAULT_ID_FIELD); } else { $out = static::fromMongoObjects($result); } break; case Verbs::GET: if ($continue && !$single) { return parent::addToTransaction(null, $id); } $filter = [static::DEFAULT_ID_FIELD => $id]; $criteria = $this->buildCriteriaArray($filter, null, $ssFilters); $result = $this->collection->findOne($criteria, $fieldArray); if (empty($result)) { throw new NotFoundException("Record with id '{$id}' not found."); } $out = static::fromMongoObjects($result); break; } return $out; }
{ $jsonevents = ""; $jsoncounter = 0; foreach ($thejson['response'] as $jsonevent) { $jsoncounter++; if($jsoncount==0 || $jsoncount == $jsoncounter) { $jsonevents .= $jsonevent['Event']['id']; } else { $jsonevents .= $jsonevent['Event']['id'] .', '; } } $retval = $collection->findAndModify( array("id" => $array['id']), array('$set' => array('misp' => "true",'misp_event' => $jsonevents)) ); $counter++; } } } } echo "Found " . $counter . " Samples in MISP"; } else { echo "MISP config is set to False"; } ?>
/** * 通过findAndModify的方式,插入数据。 * 这样可以使用$a['a.b']的方式插入结构为{a:{b:xxx}}的数据,这是insert所不能办到的 * 采用update也可以实现类似的效果,区别在于findAndModify可以返回插入之后的新数据,更接近insert的原始行为 * * @param array $a * @return array */ public function insertByFindAndModify($a) { if (empty($a)) { throw new \Exception('$a is NULL'); } array_unset_recursive($a, array('__CREATE_TIME__', '__MODIFY_TIME__', '__REMOVED__')); if (!isset($a['__CREATE_TIME__'])) { $a['__CREATE_TIME__'] = new \MongoDate(); } if (!isset($a['__MODIFY_TIME__'])) { $a['__MODIFY_TIME__'] = new \MongoDate(); } if (!isset($a['__REMOVED__'])) { $a['__REMOVED__'] = false; } $query = array('_id' => new \MongoId()); $a = array('$set' => $a); $fields = null; $options = array('new' => true, 'upsert' => true); return parent::findAndModify($query, $a, $fields, $options); }