/**
  * Run the ApplyOperation job
  * @throws \Exception
  */
 public function perform()
 {
     try {
         $this->debugLog("[JOBID " . $this->job->payload['id'] . "] ApplyOperation::perform() start");
         $timer = new \Tripod\Timer();
         $timer->start();
         $this->validateArgs();
         $statsConfig = array();
         if (isset($this->args['statsConfig'])) {
             $statsConfig['statsConfig'] = $this->args['statsConfig'];
         }
         // set the config to what is received
         \Tripod\Mongo\Config::setConfig($this->args[self::TRIPOD_CONFIG_KEY]);
         $this->getStat()->increment(MONGO_QUEUE_APPLY_OPERATION_JOB . '.' . SUBJECT_COUNT, count($this->args[self::SUBJECTS_KEY]));
         foreach ($this->args[self::SUBJECTS_KEY] as $subject) {
             $opTimer = new \Tripod\Timer();
             $opTimer->start();
             $impactedSubject = $this->createImpactedSubject($subject);
             $impactedSubject->update();
             $opTimer->stop();
             // stat time taken to perform operation for the given subject
             $this->getStat()->timer(MONGO_QUEUE_APPLY_OPERATION . '.' . $subject['operation'], $opTimer->result());
         }
         $timer->stop();
         // stat time taken to process job, from time it was picked up
         $this->getStat()->timer(MONGO_QUEUE_APPLY_OPERATION_SUCCESS, $timer->result());
         $this->debugLog("[JOBID " . $this->job->payload['id'] . "] ApplyOperation::perform() done in {$timer->result()}ms");
     } catch (\Exception $e) {
         $this->getStat()->increment(MONGO_QUEUE_APPLY_OPERATION_FAIL);
         $this->errorLog("Caught exception in " . get_class($this) . ": " . $e->getMessage());
         throw $e;
     }
 }
Exemple #2
0
    if (array_key_exists("from", $tableSpec)) {
        \Tripod\Mongo\Config::getInstance()->setMongoCursorTimeout(-1);
        print "Generating {$tableId}";
        $tripod = new \Tripod\Mongo\Driver($tableSpec['from'], $storeName, array('stat' => $stat));
        $tTables = $tripod->getTripodTables();
        if ($id) {
            print " for {$id}....\n";
            $tTables->generateTableRows($tableId, $id);
        } else {
            print " for all tables....\n";
            $tTables->generateTableRows($tableId, null, null, $queue);
        }
    }
}
$t = new \Tripod\Timer();
$t->start();
\Tripod\Mongo\Config::setConfig(json_decode(file_get_contents($configLocation), true));
if (isset($options['s']) || isset($options['storename'])) {
    $storeName = isset($options['s']) ? $options['s'] : $options['storename'];
} else {
    $storeName = null;
}
if (isset($options['t']) || isset($options['spec'])) {
    $tableId = isset($options['t']) ? $options['t'] : $options['spec'];
} else {
    $tableId = null;
}
if (isset($options['i']) || isset($options['id'])) {
    $id = isset($options['i']) ? $options['i'] : $options['id'];
} else {
    $id = null;
Exemple #3
0
 /**
  * @param string $tableType
  * @param string|null $resource
  * @param string|null $context
  * @param string|null $queueName Queue for background bulk generation
  * @return null //@todo: this should be a bool
  */
 public function generateTableRows($tableType, $resource = null, $context = null, $queueName = null)
 {
     $t = new \Tripod\Timer();
     $t->start();
     $this->temporaryFields = array();
     $tableSpec = Config::getInstance()->getTableSpecification($this->storeName, $tableType);
     $collection = $this->config->getCollectionForTable($this->storeName, $tableType);
     if ($tableSpec == null) {
         $this->debugLog("Could not find a table specification for {$tableType}");
         return null;
     }
     // ensure that the ID field, view type, and the impactIndex indexes are correctly set up
     $collection->createIndex(array('_id.r' => 1, '_id.c' => 1, '_id.type' => 1), array('background' => 1));
     $collection->createIndex(array('_id.type' => 1), array('background' => 1));
     $collection->createIndex(array('value.' . _IMPACT_INDEX => 1), array('background' => 1));
     // ensure any custom view indexes
     foreach (Config::getInstance()->getTableSpecifications($this->storeName) as $tSpec) {
         if (isset($tSpec['ensureIndexes']) && $tSpec['to_data_source'] == $tableSpec['to_data_source']) {
             foreach ($tSpec['ensureIndexes'] as $ensureIndex) {
                 $this->ensureIndex($collection, $ensureIndex);
             }
         }
     }
     // default the context
     $contextAlias = $this->getContextAlias($context);
     // default collection
     $from = isset($tableSpec["from"]) ? $tableSpec["from"] : $this->podName;
     $types = array();
     if (is_array($tableSpec["type"])) {
         foreach ($tableSpec["type"] as $type) {
             $types[] = array("rdf:type.u" => $this->labeller->qname_to_alias($type));
             $types[] = array("rdf:type.u" => $this->labeller->uri_to_alias($type));
         }
     } else {
         $types[] = array("rdf:type.u" => $this->labeller->qname_to_alias($tableSpec["type"]));
         $types[] = array("rdf:type.u" => $this->labeller->uri_to_alias($tableSpec["type"]));
     }
     $filter = array('$or' => $types);
     if (isset($resource)) {
         $filter["_id"] = array(_ID_RESOURCE => $this->labeller->uri_to_alias($resource), _ID_CONTEXT => $contextAlias);
     }
     $docs = $this->config->getCollectionForCBD($this->storeName, $from)->find($filter, array('maxTimeMS' => 1000000));
     foreach ($docs as $doc) {
         if ($queueName && !$resource) {
             $subject = new ImpactedSubject($doc['_id'], OP_TABLES, $this->storeName, $from, array($tableType));
             $jobOptions = array();
             if ($this->stat || !empty($this->statsConfig)) {
                 $jobOptions['statsConfig'] = $this->getStatsConfig();
             }
             $this->getApplyOperation()->createJob(array($subject), $queueName, $jobOptions);
         } else {
             // set up ID
             $generatedRow = array("_id" => array(_ID_RESOURCE => $doc["_id"][_ID_RESOURCE], _ID_CONTEXT => $doc["_id"][_ID_CONTEXT], _ID_TYPE => $tableSpec['_id']));
             $value = array('_id' => $doc['_id']);
             // everything must go in the value object todo: this is a hang over from map reduce days, engineer out once we have stability on new PHP method for M/R
             $this->addIdToImpactIndex($doc['_id'], $value);
             // need to add the doc to the impact index to be consistent with views/search etc. this is needed for discovering impacted operations
             $this->addFields($doc, $tableSpec, $value);
             if (isset($tableSpec['joins'])) {
                 $this->doJoins($doc, $tableSpec['joins'], $value, $from, $contextAlias);
             }
             if (isset($tableSpec['counts'])) {
                 $this->doCounts($doc, $tableSpec['counts'], $value);
             }
             if (isset($tableSpec['computed_fields'])) {
                 $this->doComputedFields($tableSpec, $value);
             }
             // Remove temp fields from document
             $generatedRow['value'] = array_diff_key($value, array_flip($this->temporaryFields));
             $this->truncatingSave($collection, $generatedRow);
         }
     }
     $t->stop();
     $this->timingLog(MONGO_CREATE_TABLE, array('type' => $tableSpec['type'], 'duration' => $t->result(), 'filter' => $filter, 'from' => $from));
     $this->getStat()->timer(MONGO_CREATE_TABLE . ".{$tableType}", $t->result());
 }
Exemple #4
0
 * @param array $triples
 * @param array $errors
 * @param string $podName
 * @param string $storeName
 */
function load(\Tripod\Mongo\TriplesUtil $loader, $subject, array $triples, array &$errors, $podName, $storeName)
{
    try {
        $loader->loadTriplesAbout($subject, $triples, $storeName, $podName);
    } catch (Exception $e) {
        print "Exception for subject {$subject} failed with message: " . $e->getMessage() . "\n";
        $errors[] = $subject;
    }
}
$timer = new \Tripod\Timer();
$timer->start();
if ($argc != 4) {
    echo "usage: ./loadTriples.php storename podname tripodConfig.json < ntriplesdata\n";
    die;
}
array_shift($argv);
$storeName = $argv[0];
$podName = $argv[1];
\Tripod\Mongo\Config::setConfig(json_decode(file_get_contents($argv[2]), true));
$i = 0;
$currentSubject = "";
$triples = array();
$errors = array();
// array of subjects that failed to insert, even after retry...
$loader = new \Tripod\Mongo\TriplesUtil();
while (($line = fgets(STDIN)) !== false) {
 /**
  * Run the DiscoverImpactedSubjects job
  * @throws \Exception
  */
 public function perform()
 {
     try {
         $this->debugLog("[JOBID " . $this->job->payload['id'] . "] DiscoverImpactedSubjects::perform() start");
         $timer = new \Tripod\Timer();
         $timer->start();
         $this->validateArgs();
         // set the config to what is received
         \Tripod\Mongo\Config::setConfig($this->args[self::TRIPOD_CONFIG_KEY]);
         $statsConfig = array();
         if (isset($this->args['statsConfig'])) {
             $statsConfig['statsConfig'] = $this->args['statsConfig'];
         }
         $tripod = $this->getTripod($this->args[self::STORE_NAME_KEY], $this->args[self::POD_NAME_KEY], $statsConfig);
         $operations = $this->args[self::OPERATIONS_KEY];
         $subjectsAndPredicatesOfChange = $this->args[self::CHANGES_KEY];
         $subjectCount = 0;
         foreach ($operations as $op) {
             /** @var \Tripod\Mongo\Composites\IComposite $composite */
             $composite = $tripod->getComposite($op);
             $modifiedSubjects = $composite->getImpactedSubjects($subjectsAndPredicatesOfChange, $this->args[self::CONTEXT_ALIAS_KEY]);
             if (!empty($modifiedSubjects)) {
                 /* @var $subject \Tripod\Mongo\ImpactedSubject */
                 foreach ($modifiedSubjects as $subject) {
                     $subjectCount++;
                     $subjectTimer = new \Tripod\Timer();
                     $subjectTimer->start();
                     if (isset($this->args[self::QUEUE_KEY]) || count($subject->getSpecTypes()) == 0) {
                         $queueName = isset($this->args[self::QUEUE_KEY]) ? $this->args[self::QUEUE_KEY] : Config::getApplyQueueName();
                         $this->addSubjectToQueue($subject, $queueName);
                     } else {
                         $specsGroupedByQueue = array();
                         foreach ($subject->getSpecTypes() as $specType) {
                             $spec = null;
                             switch ($subject->getOperation()) {
                                 case OP_VIEWS:
                                     $spec = Config::getInstance()->getViewSpecification($this->args[self::STORE_NAME_KEY], $specType);
                                     break;
                                 case OP_TABLES:
                                     $spec = Config::getInstance()->getTableSpecification($this->args[self::STORE_NAME_KEY], $specType);
                                     break;
                                 case OP_SEARCH:
                                     $spec = Config::getInstance()->getSearchDocumentSpecification($this->args[self::STORE_NAME_KEY], $specType);
                                     break;
                             }
                             if (!$spec || !isset($spec['queue'])) {
                                 if (!$spec) {
                                     $spec = array();
                                 }
                                 $spec['queue'] = Config::getApplyQueueName();
                             }
                             if (!isset($specsGroupedByQueue[$spec['queue']])) {
                                 $specsGroupedByQueue[$spec['queue']] = array();
                             }
                             $specsGroupedByQueue[$spec['queue']][] = $specType;
                         }
                         foreach ($specsGroupedByQueue as $queueName => $specs) {
                             $queuedSubject = new \Tripod\Mongo\ImpactedSubject($subject->getResourceId(), $subject->getOperation(), $subject->getStoreName(), $subject->getPodName(), $specs);
                             $this->addSubjectToQueue($queuedSubject, $queueName);
                         }
                     }
                     $subjectTimer->stop();
                     // stat time taken to discover impacted subjects for the given subject of change
                     $this->getStat()->timer(MONGO_QUEUE_DISCOVER_SUBJECT, $subjectTimer->result());
                 }
                 if (!empty($this->subjectsGroupedByQueue)) {
                     foreach ($this->subjectsGroupedByQueue as $queueName => $subjects) {
                         $this->getApplyOperation()->createJob($subjects, $queueName, $statsConfig);
                     }
                     $this->subjectsGroupedByQueue = array();
                 }
             }
         }
         // stat time taken to process item, from time it was created (queued)
         $timer->stop();
         $this->getStat()->timer(MONGO_QUEUE_DISCOVER_SUCCESS, $timer->result());
         $this->debugLog("[JOBID " . $this->job->payload['id'] . "] DiscoverImpactedSubjects::perform() done in {$timer->result()}ms");
         $this->getStat()->increment(MONGO_QUEUE_DISCOVER_JOB . '.' . SUBJECT_COUNT, $subjectCount);
     } catch (\Exception $e) {
         $this->getStat()->increment(MONGO_QUEUE_DISCOVER_FAIL);
         $this->errorLog("Caught exception in " . get_class($this) . ": " . $e->getMessage());
         throw $e;
     }
 }
Exemple #6
0
 /**
  * Given a specific $viewId, generates a single view for the $resource
  * @param string $viewId
  * @param string|null $resource
  * @param string|null $context
  * @param string|null $queueName Queue for background bulk generation
  * @throws \Tripod\Exceptions\ViewException
  * @return array
  */
 public function generateView($viewId, $resource = null, $context = null, $queueName = null)
 {
     $contextAlias = $this->getContextAlias($context);
     $viewSpec = Config::getInstance()->getViewSpecification($this->storeName, $viewId);
     if ($viewSpec == null) {
         $this->debugLog("Could not find a view specification for {$resource} with viewId '{$viewId}'");
         return null;
     } else {
         $t = new \Tripod\Timer();
         $t->start();
         $from = $this->getFromCollectionForViewSpec($viewSpec);
         $collection = $this->config->getCollectionForView($this->storeName, $viewId);
         if (!isset($viewSpec['joins'])) {
             throw new \Tripod\Exceptions\ViewException('Could not find any joins in view specification - usecase better served with select()');
         }
         // ensure that the ID field, view type, and the impactIndex indexes are correctly set up
         $collection->createIndex(array('_id.r' => 1, '_id.c' => 1, '_id.type' => 1), array('background' => 1));
         $collection->createIndex(array('_id.type' => 1), array('background' => 1));
         $collection->createIndex(array('value.' . _IMPACT_INDEX => 1), array('background' => 1));
         // ensure any custom view indexes
         if (isset($viewSpec['ensureIndexes'])) {
             foreach ($viewSpec['ensureIndexes'] as $ensureIndex) {
                 $collection->createIndex($ensureIndex, array('background' => 1));
             }
         }
         $types = array();
         // this is used to filter the CBD table to speed up the view creation
         if (is_array($viewSpec["type"])) {
             foreach ($viewSpec["type"] as $type) {
                 $types[] = array("rdf:type.u" => $this->labeller->qname_to_alias($type));
                 $types[] = array("rdf:type.u" => $this->labeller->uri_to_alias($type));
             }
         } else {
             $types[] = array("rdf:type.u" => $this->labeller->qname_to_alias($viewSpec["type"]));
             $types[] = array("rdf:type.u" => $this->labeller->uri_to_alias($viewSpec["type"]));
         }
         $filter = array('$or' => $types);
         if (isset($resource)) {
             $resourceAlias = $this->labeller->uri_to_alias($resource);
             $filter["_id"] = array(_ID_RESOURCE => $resourceAlias, _ID_CONTEXT => $contextAlias);
         }
         $docs = $this->config->getCollectionForCBD($this->storeName, $from)->find($filter, array('maxTimeMS' => \Tripod\Mongo\Config::getInstance()->getMongoCursorTimeout()));
         foreach ($docs as $doc) {
             if ($queueName && !$resource) {
                 $subject = new ImpactedSubject($doc['_id'], OP_VIEWS, $this->storeName, $from, array($viewId));
                 $jobOptions = array();
                 if ($this->stat || !empty($this->statsConfig)) {
                     $jobOptions['statsConfig'] = $this->getStatsConfig();
                 }
                 $this->getApplyOperation()->createJob(array($subject), $queueName, $jobOptions);
             } else {
                 // set up ID
                 $id = array("_id" => array(_ID_RESOURCE => $doc["_id"][_ID_RESOURCE], _ID_CONTEXT => $doc["_id"][_ID_CONTEXT], _ID_TYPE => $viewSpec['_id']));
                 $generatedView = $id;
                 $value = array();
                 // everything must go in the value object todo: this is a hang over from map reduce days, engineer out once we have stability on new PHP method for M/R
                 $value[_GRAPHS] = array();
                 $buildImpactIndex = true;
                 if (isset($viewSpec['ttl'])) {
                     $buildImpactIndex = false;
                     $value[_EXPIRES] = \Tripod\Mongo\DateUtil::getMongoDate($this->getExpirySecFromNow($viewSpec['ttl']) * 1000);
                 } else {
                     $value[_IMPACT_INDEX] = array($doc['_id']);
                 }
                 $this->doJoins($doc, $viewSpec['joins'], $value, $from, $contextAlias, $buildImpactIndex);
                 // add top level properties
                 $value[_GRAPHS][] = $this->extractProperties($doc, $viewSpec, $from);
                 $generatedView['value'] = $value;
                 $collection->replaceOne($id, $generatedView, ['upsert' => true]);
             }
         }
         $t->stop();
         $this->timingLog(MONGO_CREATE_VIEW, array('view' => $viewSpec['type'], 'duration' => $t->result(), 'filter' => $filter, 'from' => $from));
         $this->getStat()->timer(MONGO_CREATE_VIEW . ".{$viewId}", $t->result());
     }
 }
 /**
  * @param array $query
  * @param string $type
  * @param Collection|null $collection
  * @param array $includeProperties
  * @param int $cursorSize
  * @return MongoGraph
  */
 protected function fetchGraph($query, $type, $collection = null, $includeProperties = array(), $cursorSize = 101)
 {
     $graph = new MongoGraph();
     $t = new \Tripod\Timer();
     $t->start();
     if ($collection == null) {
         $collection = $this->collection;
         $collectionName = $collection->getCollectionName();
     } else {
         $collectionName = $collection->getCollectionName();
     }
     if (empty($includeProperties)) {
         $cursor = $collection->find($query);
     } else {
         $fields = array();
         foreach ($includeProperties as $property) {
             $fields[$this->labeller->uri_to_alias($property)] = true;
         }
         $cursor = $collection->find($query, array('projection' => $fields, 'batchSize' => $cursorSize));
     }
     $ttlExpiredResources = false;
     $retries = 1;
     $exception = null;
     $cursorSuccess = false;
     do {
         try {
             foreach ($cursor as $result) {
                 // handle MONGO_VIEWS that have expired due to ttl. These are expired
                 // on read (lazily) rather than on write
                 if ($type == MONGO_VIEW && array_key_exists(_EXPIRES, $result['value'])) {
                     // if expires < current date, regenerate view..
                     $currentDate = \Tripod\Mongo\DateUtil::getMongoDate();
                     if ($result['value'][_EXPIRES]->__toString() < $currentDate) {
                         // regenerate!
                         $this->generateView($result['_id']['type'], $result['_id']['r']);
                     }
                 }
                 $graph->add_tripod_array($result);
             }
             $cursorSuccess = true;
         } catch (\Exception $e) {
             self::getLogger()->error("CursorException attempt " . $retries . ". Retrying...:" . $e->getMessage());
             sleep(1);
             $retries++;
             $exception = $e;
         }
     } while ($retries <= Config::CONNECTION_RETRIES && $cursorSuccess === false);
     if ($cursorSuccess === false) {
         self::getLogger()->error("CursorException failed after " . $retries . " attempts (MAX:" . Config::CONNECTION_RETRIES . "): " . $e->getMessage());
         throw new \Exception($exception);
     }
     if ($ttlExpiredResources) {
         // generate views and retry...
         $this->debugLog("One or more view had exceeded TTL was regenerated - request again...");
         $graph = $this->fetchGraph($query, $type, $collection);
     }
     $t->stop();
     $this->timingLog($type, array('duration' => $t->result(), 'query' => $query, 'collection' => $collectionName));
     if ($type == MONGO_VIEW) {
         if (array_key_exists("_id.type", $query)) {
             $this->getStat()->timer("{$type}.{$query["_id.type"]}", $t->result());
         } else {
             if (array_key_exists("_id", $query) && array_key_exists("type", $query["_id"])) {
                 $this->getStat()->timer("{$type}.{$query["_id"]["type"]}", $t->result());
             }
         }
     } else {
         $this->getStat()->timer("{$type}.{$collectionName}", $t->result());
     }
     return $graph;
 }
Exemple #8
0
 /**
  * Selects $fields from the result set determined by $query.
  * Returns an array of all results, each array element is a CBD graph, keyed by r
  * @param array $query
  * @param array $fields array of fields, in the same format as prescribed by MongoPHP
  * @param null $sortBy
  * @param null $limit
  * @param int $offset
  * @param null $context
  * @return array MongoGraphs, keyed by subject
  */
 public function select($query, $fields, $sortBy = null, $limit = null, $offset = 0, $context = null)
 {
     $t = new \Tripod\Timer();
     $t->start();
     $contextAlias = $this->getContextAlias($context);
     // make sure context is represented - but not at the expense of $ operands queries failing
     if (array_key_exists('_id', $query) && is_array($query["_id"])) {
         if (!array_key_exists(_ID_CONTEXT, $query['_id']) && array_key_exists(_ID_RESOURCE, $query['_id'])) {
             // add context
             $query["_id"][_ID_CONTEXT] = $contextAlias;
         } else {
             // check query does not have a $ operand
             foreach ($query["_id"] as $key => $queryProps) {
                 if (substr($key, 0, 1) == '$' && is_array($queryProps)) {
                     foreach ($queryProps as $index => $queryProp) {
                         if (is_array($queryProp) && array_key_exists(_ID_RESOURCE, $queryProp)) {
                             $queryProp[_ID_CONTEXT] = $contextAlias;
                             $query["_id"][$key][$index] = $queryProp;
                         }
                     }
                 }
             }
         }
     } else {
         if (!array_key_exists('_id', $query)) {
             // this query did not have _id referenced at all - just add an _id.c clause
             $query["_id." . _ID_CONTEXT] = $contextAlias;
         }
     }
     $findOptions = array('projection' => $fields);
     if (!empty($limit)) {
         $findOptions['skip'] = (int) $offset;
         $findOptions['limit'] = (int) $limit;
     }
     if (isset($sortBy)) {
         $findOptions['sort'] = $sortBy;
     }
     $results = $this->collection->find($query, $findOptions);
     $t->stop();
     $this->timingLog(MONGO_SELECT, array('duration' => $t->result(), 'query' => $query));
     $this->getStat()->timer(MONGO_SELECT . ".{$this->podName}", $t->result());
     $rows = array();
     $count = $this->collection->count($query);
     foreach ($results as $doc) {
         $row = array();
         foreach ($doc as $key => $value) {
             if ($key == _ID_KEY || $key === _VERSION) {
                 $row[$key] = $value;
             } else {
                 if (array_key_exists(VALUE_LITERAL, $value)) {
                     $row[$key] = $value[VALUE_LITERAL];
                 } else {
                     if (array_key_exists(VALUE_URI, $value)) {
                         $row[$key] = $value[VALUE_URI];
                     } else {
                         $row[$key] = array();
                         // possible array of values
                         foreach ($value as $v) {
                             $row[$key][] = array_key_exists(VALUE_LITERAL, $v) ? $v[VALUE_LITERAL] : $v[VALUE_URI];
                         }
                     }
                 }
             }
         }
         $rows[] = $row;
     }
     $result = array("head" => array("count" => $count, "offset" => $offset, "limit" => $limit), "results" => $rows);
     return $result;
 }
 /**
  * @param array $rdfTypes
  * @param string $resource
  * @param string $context
  * @return array
  * @throws \Exception
  */
 public function generateSearchDocumentsBasedOnRdfTypes(array $rdfTypes, $resource, $context)
 {
     if (empty($resource)) {
         throw new \Exception("Resource must be specified");
     }
     if (empty($context)) {
         throw new \Exception("Context must be specified");
     }
     // this is what is returned
     $generatedSearchDocuments = array();
     $timer = new \Tripod\Timer();
     $timer->start();
     foreach ($rdfTypes as $rdfType) {
         $specs = Config::getInstance()->getSearchDocumentSpecifications($this->storeName, $rdfType);
         if (empty($specs)) {
             continue;
         }
         // no point doing anything else if there is no spec for the type
         foreach ($specs as $searchSpec) {
             $generatedSearchDocuments[] = $this->generateSearchDocumentBasedOnSpecId($searchSpec['_id'], $resource, $context);
         }
     }
     $timer->stop();
     //echo "\n\tTook " . $timer->result() . " ms to generate search documents\n";
     return $generatedSearchDocuments;
 }
 /**
  * @param string $searchDocumentType
  * @param string|null $resourceUri
  * @param string|null $context
  * @param string|null $queueName
  */
 public function generateSearchDocuments($searchDocumentType, $resourceUri = null, $context = null, $queueName = null)
 {
     $t = new \Tripod\Timer();
     $t->start();
     // default the context
     $contextAlias = $this->getContextAlias($context);
     $spec = \Tripod\Mongo\Config::getInstance()->getSearchDocumentSpecification($this->getStoreName(), $searchDocumentType);
     if ($resourceUri) {
         $this->generateAndIndexSearchDocuments($resourceUri, $contextAlias, $spec['from'], $searchDocumentType);
         return;
     }
     // default collection
     $from = isset($spec["from"]) ? $spec["from"] : $this->podName;
     $types = array();
     if (is_array($spec["type"])) {
         foreach ($spec["type"] as $type) {
             $types[] = array("rdf:type.u" => $this->labeller->qname_to_alias($type));
             $types[] = array("rdf:type.u" => $this->labeller->uri_to_alias($type));
         }
     } else {
         $types[] = array("rdf:type.u" => $this->labeller->qname_to_alias($spec["type"]));
         $types[] = array("rdf:type.u" => $this->labeller->uri_to_alias($spec["type"]));
     }
     $filter = array('$or' => $types);
     if (isset($resource)) {
         $filter["_id"] = array(_ID_RESOURCE => $this->labeller->uri_to_alias($resource), _ID_CONTEXT => $contextAlias);
     }
     $docs = $this->config->getCollectionForCBD($this->getStoreName(), $from)->find($filter, array('maxTimeMS' => $this->config->getMongoCursorTimeout()));
     foreach ($docs as $doc) {
         if ($queueName && !$resourceUri) {
             $subject = new ImpactedSubject($doc['_id'], OP_SEARCH, $this->storeName, $from, array($searchDocumentType));
             $jobOptions = array();
             if ($this->stat || !empty($this->statsConfig)) {
                 $jobOptions['statsConfig'] = $this->getStatsConfig();
             }
             $this->getApplyOperation()->createJob(array($subject), $queueName, $jobOptions);
         } else {
             $this->generateAndIndexSearchDocuments($doc[_ID_KEY][_ID_RESOURCE], $doc[_ID_KEY][_ID_CONTEXT], $spec['from'], $searchDocumentType);
         }
     }
     $t->stop();
     $this->timingLog(MONGO_CREATE_TABLE, array('type' => $spec['type'], 'duration' => $t->result(), 'filter' => $filter, 'from' => $from));
     $this->getStat()->timer(MONGO_CREATE_SEARCH_DOC . ".{$searchDocumentType}", $t->result());
 }
Exemple #11
0
 /**
  * Processes each subject synchronously
  * @param array $subjectsAndPredicatesOfChange
  * @param string $contextAlias
  */
 protected function processSyncOperations(array $subjectsAndPredicatesOfChange, $contextAlias)
 {
     foreach ($this->getSyncOperations() as $op) {
         /** @var \Tripod\Mongo\Composites\IComposite $composite */
         $composite = $this->tripod->getComposite($op);
         $opSubjects = $composite->getImpactedSubjects($subjectsAndPredicatesOfChange, $contextAlias);
         if (!empty($opSubjects)) {
             foreach ($opSubjects as $subject) {
                 /* @var $subject ImpactedSubject */
                 $t = new \Tripod\Timer();
                 $t->start();
                 // Call update on the subject, rather than the composite directly, in case the change was to
                 // another pod
                 $subject->update($subject);
                 $t->stop();
                 $this->timingLog(MONGO_ON_THE_FLY_MR, array("duration" => $t->result(), "storeName" => $subject->getStoreName(), "podName" => $subject->getPodName(), "resourceId" => $subject->getResourceId()));
                 $this->getStat()->timer(MONGO_ON_THE_FLY_MR, $t->result());
             }
         }
     }
 }
 /**
  * @param string $q
  * @param string $type
  * @param array $indices
  * @param array $fields
  * @param int $limit
  * @param int $offset
  * @return array|mixed
  * @throws \Tripod\Exceptions\SearchException
  */
 public function search($q, $type, $indices = array(), $fields = array(), $limit = 10, $offset = 0)
 {
     if (empty($q)) {
         throw new \Tripod\Exceptions\SearchException("You must specify a query");
     }
     if (empty($type)) {
         throw new \Tripod\Exceptions\SearchException("You must specify the search document type to restrict the query to");
     }
     if (empty($indices)) {
         throw new \Tripod\Exceptions\SearchException("You must specify at least one index from the search document specification to query against");
     }
     if (empty($fields)) {
         throw new \Tripod\Exceptions\SearchException("You must specify at least one field from the search document specification to return");
     }
     if (!is_numeric($limit) || $limit < 0) {
         throw new \Tripod\Exceptions\SearchException("Value for limit must be a positive number");
     }
     if (!is_numeric($offset) || $offset < 0) {
         throw new \Tripod\Exceptions\SearchException("Value for offset must be a positive number");
     }
     $original_terms = explode(" ", trim(strtolower($q)));
     $terms = array_values(array_diff($original_terms, $this->stopWords));
     // todo: this means if all the words entered were stop words, then use the orginal terms rather than do nothing!
     if (empty($terms)) {
         $terms = $original_terms;
     }
     $regexes = array();
     foreach ($terms as $t) {
         $regexes[] = new Regex("{$t}", '');
     }
     $query = array();
     $query['_id.type'] = $type;
     if (count($indices) == 1) {
         $searchIndex = $indices[0];
         $query[$searchIndex] = array('$all' => $regexes);
     } else {
         $query['$or'] = array();
         foreach ($indices as $searchIndex) {
             $query['$or'][] = array("{$searchIndex}" => array('$all' => $regexes));
         }
     }
     $fieldsToReturn = array();
     foreach ($fields as $field) {
         $fieldsToReturn[$field] = 1;
     }
     $searchTimer = new \Tripod\Timer();
     $searchTimer->start();
     $cursor = $this->config->getCollectionForSearchDocument($this->storeName, $type)->find($query, array('projection' => $fieldsToReturn, 'limit' => $limit, 'skip' => $offset));
     $searchResults = array();
     $searchResults['head'] = array();
     $searchResults['head']['count'] = "";
     $searchResults['head']['limit'] = $limit;
     $searchResults['head']['offset'] = $offset;
     $searchResults['head']['duration'] = "";
     $searchResults['head']['query'] = $q;
     $searchResults['head']['query_terms_used'] = $terms;
     $searchResults['results'] = array();
     $count = $this->config->getCollectionForSearchDocument($this->storeName, $type)->count($query);
     if ($count > 0) {
         $searchResults['head']['count'] = $count;
         foreach ($cursor as $result) {
             // if more than one field has been asked for we need to
             // enumerate them in the results returned. However if only one has been
             // asked for then results is just set to that single fields value.
             if (count($fields) > 1) {
                 $r = array();
                 foreach ($fields as $field) {
                     if (isset($result[$field])) {
                         $r[$field] = $result[$field];
                     } else {
                         $r[$field] = "";
                     }
                 }
                 $searchResults['results'][] = $r;
             } else {
                 $searchResults['results'][] = $result[$fields[0]];
             }
         }
     } else {
         $searchResults['head']['count'] = 0;
     }
     $searchTimer->stop();
     $searchResults['head']["duration"] = $searchTimer->result() . ' ms';
     return $searchResults;
 }