/** * Given a class, object id, set of stateful ids and a list of changed fields (in a special format), * return what statefulids need updating in this index * * Internal function used by SearchUpdater. * * @param $class * @param $id * @param $statefulids * @param $fields * @return array */ public function getDirtyIDs($class, $id, $statefulids, $fields) { $dirty = array(); // First, if this object is directly contained in the index, add it foreach ($this->classes as $searchclass => $options) { if ($searchclass == $class || $options['include_children'] && is_subclass_of($class, $searchclass)) { $base = ClassInfo::baseDataClass($searchclass); $dirty[$base] = array(); foreach ($statefulids as $statefulid) { $key = serialize($statefulid); $dirty[$base][$key] = $statefulid; } } } $current = SearchVariant::current_state(); // Then, for every derived field foreach ($this->getDerivedFields() as $derivation) { // If the this object is a subclass of any of the classes we want a field from if (!SearchIntrospection::is_subclass_of($class, $derivation['classes'])) { continue; } if (!array_intersect_key($fields, $derivation['fields'])) { continue; } foreach (SearchVariant::reindex_states($class, false) as $state) { SearchVariant::activate_state($state); $ids = array($id); foreach ($derivation['chain'] as $step) { if ($step['through'] == 'has_one') { $sql = new SQLQuery('"ID"', '"' . $step['class'] . '"', '"' . $step['foreignkey'] . '" IN (' . implode(',', $ids) . ')'); singleton($step['class'])->extend('augmentSQL', $sql); $ids = $sql->execute()->column(); } else { if ($step['through'] == 'has_many') { $sql = new SQLQuery('"' . $step['class'] . '"."ID"', '"' . $step['class'] . '"', '"' . $step['otherclass'] . '"."ID" IN (' . implode(',', $ids) . ')'); $sql->addInnerJoin($step['otherclass'], '"' . $step['class'] . '"."ID" = "' . $step['otherclass'] . '"."' . $step['foreignkey'] . '"'); singleton($step['class'])->extend('augmentSQL', $sql); $ids = $sql->execute()->column(); } } } SearchVariant::activate_state($current); if ($ids) { $base = $derivation['base']; if (!isset($dirty[$base])) { $dirty[$base] = array(); } foreach ($ids as $id) { $statefulid = array('id' => $id, 'state' => $state); $key = serialize($statefulid); $dirty[$base][$key] = $statefulid; } } } } return $dirty; }
/** * Explicitly invoke the process that performs the group * processing. Can be run either by a background task or a queuedjob. * * Does not commit changes to the index, so this must be controlled externally. * * @param LoggerInterface $logger * @param SolrIndex $indexInstance * @param array $state * @param string $class * @param int $groups * @param int $group */ public function runGroup(LoggerInterface $logger, SolrIndex $indexInstance, $state, $class, $groups, $group) { // Set time limit and state increase_time_limit_to(); SearchVariant::activate_state($state); $logger->info("Adding {$class}"); // Prior to adding these records to solr, delete existing solr records $this->clearRecords($indexInstance, $class, $groups, $group); // Process selected records in this class $items = $this->getRecordsInGroup($indexInstance, $class, $groups, $group); $processed = array(); foreach ($items as $item) { $processed[] = $item->ID; // By this point, obsolete classes/states have been removed in processVariant // and obsolete records have been removed in clearRecords $indexInstance->add($item); $item->destroy(); } $logger->info("Updated " . implode(',', $processed)); // This will slow down things a tiny bit, but it is done so that we don't timeout to the database during a reindex DB::query('SELECT 1'); $logger->info("Done"); }
/** * @deprecated since version 2.0.0 */ protected function runFrom($index, $class, $start, $variantstate) { DeprecationTest_Deprecation::notice('2.0.0', 'Solr_Reindex now uses a new grouping mechanism'); // Set time limit and state increase_time_limit_to(); SearchVariant::activate_state($variantstate); // Generate filtered list $items = DataList::create($class)->limit($this->config()->recordsPerRequest, $start); // Add child filter $classes = $index->getClasses(); $options = $classes[$class]; if (!$options['include_children']) { $items = $items->filter('ClassName', $class); } // Process selected records in this class $this->getLogger()->info("Adding {$class}"); foreach ($items->sort("ID") as $item) { $this->getLogger()->debug($item->ID); // See SearchUpdater_ObjectHandler::triggerReindex $item->triggerReindex(); $item->destroy(); } $this->getLogger()->info("Done"); }
/** * Generates the list of indexes to process for the dirty items * * @return array */ protected function prepareIndexes() { $originalState = SearchVariant::current_state(); $dirtyIndexes = array(); $dirty = $this->getSource(); $indexes = FullTextSearch::get_indexes(); foreach ($dirty as $base => $statefulids) { if (!$statefulids) { continue; } foreach ($statefulids as $statefulid) { $state = $statefulid['state']; $ids = $statefulid['ids']; SearchVariant::activate_state($state); // Ensure that indexes for all new / updated objects are included $objs = DataObject::get($base)->byIDs(array_keys($ids)); foreach ($objs as $obj) { foreach ($ids[$obj->ID] as $index) { if (!$indexes[$index]->variantStateExcluded($state)) { $indexes[$index]->add($obj); $dirtyIndexes[$index] = $indexes[$index]; } } unset($ids[$obj->ID]); } // Generate list of records that do not exist and should be removed foreach ($ids as $id => $fromindexes) { foreach ($fromindexes as $index) { if (!$indexes[$index]->variantStateExcluded($state)) { $indexes[$index]->delete($base, $id, $state); $dirtyIndexes[$index] = $indexes[$index]; } } } } } SearchVariant::activate_state($originalState); return $dirtyIndexes; }
protected function runFrom($index, $class, $start, $variantstate) { $classes = $index->getClasses(); $options = $classes[$class]; $verbose = isset($_GET['verbose']); SearchVariant::activate_state($variantstate); $includeSubclasses = $options['include_children']; $filter = $includeSubclasses ? "" : '"ClassName" = \'' . $class . "'"; $items = DataList::create($class)->where($filter)->limit($this->stat('recordsPerRequest'), $start); if ($verbose) { echo "Adding {$class}"; } foreach ($items as $item) { if ($verbose) { echo $item->ID . ' '; } // See SearchUpdater_ObjectHandler::triggerReindex $item->triggerReindex(); $item->destroy(); } if ($verbose) { echo "Done "; } }