Skip to content

Commit

Permalink
Merge pull request #152 from techfromsage/TA-1913-SupportMongoIndexOp…
Browse files Browse the repository at this point in the history
…tionsInTripodConfig

TA-1913 - Support Mongo index options in Tripod config
  • Loading branch information
astilla authored Dec 11, 2024
2 parents 0db75e5 + 6c0d440 commit 499eabb
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 36 deletions.
22 changes: 16 additions & 6 deletions src/mongo/Config.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,24 @@ protected function loadConfig(array $config)
// Ensure indexes are legal
if (array_key_exists("indexes", $podConfig)) {
$this->indexes[$storeName][$podName] = [];

foreach ($podConfig["indexes"] as $indexName => $indexFields) {

$this->indexes[$storeName][$podName][$indexName] = $indexFields;

$indexKeys = array_keys($indexFields);
if (is_numeric($indexKeys[0])) {
// New format config - two arrays, where second is index options (e.g. unique=>true, sparse=>true)
$cardinalityIndexFields = $indexFields[0];
} else {
// Standard format config - single array
$cardinalityIndexFields = $indexFields;
}

// check no more than 1 indexField is an array to ensure Mongo will be able to create compound indexes
if (count($indexFields) > 1) {
if (count($cardinalityIndexFields) > 1) {
$fieldsThatAreArrays = 0;
foreach ($indexFields as $field => $fieldVal) {
foreach ($cardinalityIndexFields as $field => $fieldVal) {
$cardinalityField = str_replace('.value', '', $field);
if (!array_key_exists($cardinalityField, $this->cardinality[$storeName][$podName]) ||
$this->cardinality[$storeName][$podName][$cardinalityField] != 1) {
Expand All @@ -261,10 +274,7 @@ protected function loadConfig(array $config)
throw new \Tripod\Exceptions\ConfigException("Compound index $indexName has more than one field with cardinality > 1 - mongo will not be able to build this index");
}
}
} // @codeCoverageIgnoreStart
// @codeCoverageIgnoreEnd

$this->indexes[$storeName][$podName][$indexName] = $indexFields;
}
}
}
}
Expand Down
46 changes: 26 additions & 20 deletions src/mongo/util/IndexUtils.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public function ensureIndexes($reindex=false,$storeName=null,$background=true)
{
continue;
}

if ($reindex)
{
$collection = $config->getCollectionForCBD($storeName, $collectionName);
Expand All @@ -37,32 +38,37 @@ public function ensureIndexes($reindex=false,$storeName=null,$background=true)
$reindexedCollections[] = $collection->getNamespace();
}
}

foreach ($indexes as $indexName=>$fields)
{
$indexName = substr($indexName,0,127); // ensure max 128 chars
if (is_numeric($indexName))

$indexOptions = [
'background'=>$background
];

if (!is_numeric($indexName))
{
// no name
$config->getCollectionForCBD($storeName, $collectionName)
->createIndex(
$fields,
array(
"background"=>$background
)
);
// Named index vs. unnamed index
$indexOptions['name'] = $indexName;
}
else
{
$config->getCollectionForCBD($storeName, $collectionName)
->createIndex(
$fields,
array(
'name'=>$indexName,
"background"=>$background
)
);

$indexKeys = array_keys($fields);
if (is_numeric($indexKeys[0])) {
// New format config - two arrays, where second is index options (e.g. unique=>true, sparse=>true)
$indexFields = $fields[0];
$indexOptions = array_merge($indexOptions, $fields[1]);
} else {
// Standard format config - single array
$indexFields = $fields;
}
}

$config->getCollectionForCBD($storeName, $collectionName)
->createIndex(
$indexFields,
$indexOptions
);
}
}

// Index views
Expand Down
90 changes: 80 additions & 10 deletions test/unit/mongo/IndexUtilsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,26 @@ public function testCBDCollectionIndexesAreCreated()
$indexUtils->ensureIndexes(false, 'tripod_php_testing', true);
}

public function testCBDCollectionIndexesAreCreatedWithIndexOptions()
{
$config = $this->createMockConfig();
$collection = $this->createMockCollection();
$indexUtils = $this->createMockIndexUtils($config);

$indexOptions = ['unique' => true];

$this->setConfigForCBDIndexes($config, $indexOptions);
$this->dropIndexesShouldNeverBeCalled($collection);
$this->oneCustomAndThreeInternalTripodCBDIndexesShouldBeCreated($collection, true, $indexOptions);
$this->getCollectionForCBDShouldBeCalled_n_Times(4, $config, $collection);
$this->getCollectionForViewShouldNeverBeCalled($config);
$this->getCollectionForTableShouldNeverBeCalled($config);
$this->getCollectionForSearchDocumentShouldNeverBeCalled($config);

$indexUtils->ensureIndexes(false, 'tripod_php_testing', true);
}


public function testCBDCollectionIndexesAreCreatedInForeground()
{
$config = $this->createMockConfig();
Expand All @@ -38,6 +58,25 @@ public function testCBDCollectionIndexesAreCreatedInForeground()
$indexUtils->ensureIndexes(false, 'tripod_php_testing', false);
}

public function testCBDCollectionIndexesAreCreatedInForegroundWithIndexOptions()
{
$config = $this->createMockConfig();
$collection = $this->createMockCollection();
$indexUtils = $this->createMockIndexUtils($config);

$indexOptions = ['unique' => true];

$this->setConfigForCBDIndexes($config, $indexOptions);
$this->dropIndexesShouldNeverBeCalled($collection);
$this->oneCustomAndThreeInternalTripodCBDIndexesShouldBeCreated($collection, false, $indexOptions);
$this->getCollectionForCBDShouldBeCalled_n_Times(4, $config, $collection);
$this->getCollectionForViewShouldNeverBeCalled($config);
$this->getCollectionForTableShouldNeverBeCalled($config);
$this->getCollectionForSearchDocumentShouldNeverBeCalled($config);

$indexUtils->ensureIndexes(false, 'tripod_php_testing', false);
}

public function testCBDCollectionIndexesAreReindexed()
{
$config = $this->createMockConfig();
Expand All @@ -55,6 +94,25 @@ public function testCBDCollectionIndexesAreReindexed()
$indexUtils->ensureIndexes(true, 'tripod_php_testing', true);
}

public function testCBDCollectionIndexesAreReindexedWithIndexOptions()
{
$config = $this->createMockConfig();
$collection = $this->createMockCollection();
$indexUtils = $this->createMockIndexUtils($config);

$indexOptions = ['unique' => true];

$this->setConfigForCBDIndexes($config, $indexOptions);
$this->dropIndexesShouldBeCalled($collection);
$this->oneCustomAndThreeInternalTripodCBDIndexesShouldBeCreated($collection, true, $indexOptions);
$this->getCollectionForCBDShouldBeCalled_n_Times(5, $config, $collection);
$this->getCollectionForViewShouldNeverBeCalled($config);
$this->getCollectionForTableShouldNeverBeCalled($config);
$this->getCollectionForSearchDocumentShouldNeverBeCalled($config);

$indexUtils->ensureIndexes(true, 'tripod_php_testing', true);
}

public function testViewIndexesAreCreated()
{
$config = $this->createMockConfig();
Expand Down Expand Up @@ -407,7 +465,7 @@ protected function getCollectionForCBDShouldNeverBeCalled($mockConfig)
* @param bool $background create indexes in the background
* @return void
*/
protected function oneCustomAndThreeInternalTripodCBDIndexesShouldBeCreated($mockCollection, $background = true)
protected function oneCustomAndThreeInternalTripodCBDIndexesShouldBeCreated($mockCollection, $background = true, array $indexOptions = [])
{
// create index is called 4 times, each time with a different set of
// params that we know.
Expand All @@ -416,7 +474,7 @@ protected function oneCustomAndThreeInternalTripodCBDIndexesShouldBeCreated($moc
$mockCollection->expects($this->exactly(4))
->method('createIndex')
->withConsecutive(
[['rdf:type.u' => 1], ['name' => 'rdf_type', 'background' => $background]],
[['rdf:type.u' => 1], array_merge(['name' => 'rdf_type', 'background' => $background], $indexOptions)],
[[_ID_KEY => 1, _LOCKED_FOR_TRANS => 1], ['name' => '_lockedForTransIdx', 'background' => $background]],
[[_ID_KEY => 1, _UPDATED_TS => 1], ['name' => '_updatedTsIdx', 'background' => $background]],
[[_ID_KEY => 1, _CREATED_TS => 1], ['name' => '_createdTsIdx', 'background' => $background]]
Expand Down Expand Up @@ -496,7 +554,7 @@ protected function threeInternalTripodSearchDocIndexesShouldBeCreated($mockColle
* @param MockObject&\TripodTestConfig $mockConfig mock Config object
* @return void
*/
protected function setConfigForCBDIndexes($mockConfig)
protected function setConfigForCBDIndexes($mockConfig, array $indexOptions = [])
{
// minimal config to verify that
$config = [];
Expand All @@ -509,22 +567,34 @@ protected function setConfigForCBDIndexes($mockConfig)
'mongo' => ['type' => 'mongo', 'connection' => 'mongodb://localhost'],
];
$config['defaultContext'] = 'http://talisaspire.com/';

$config['stores'] = [
'tripod_php_testing' => [
'type' => 'mongo',
'data_source' => 'mongo',
'pods' => [
'CBD_testing' => [
'indexes' => [
'rdf_type' => [
'rdf:type.u' => 1,
],
],
],
'CBD_testing' => []
],
],
];

if (empty($indexOptions)) {
$config['stores']['tripod_php_testing']['pods']['CBD_testing']['indexes'] = [
'rdf_type' => [
'rdf:type.u' => 1,
],
];
} else {
$config['stores']['tripod_php_testing']['pods']['CBD_testing']['indexes'] = [
'rdf_type' => [
[
'rdf:type.u' => 1,
],
$indexOptions
],
];
}

$config['transaction_log'] = [
'database' => 'transactions',
'collection' => 'transaction_log',
Expand Down

0 comments on commit 499eabb

Please sign in to comment.