Skip to content

Commit d8be1b9

Browse files
authored
Merge pull request #2260 from cgrabenstein/fix-detection-of-unsued-compound-indexes
Added missing check for order of compound keys
2 parents 24c5d6c + e4288dc commit d8be1b9

File tree

2 files changed

+58
-9
lines changed

2 files changed

+58
-9
lines changed

lib/Doctrine/ODM/MongoDB/SchemaManager.php

+32-4
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414
use MongoDB\Model\IndexInfo;
1515
use function array_diff_key;
1616
use function array_filter;
17+
use function array_keys;
1718
use function array_merge;
19+
use function array_search;
1820
use function array_unique;
21+
use function array_values;
1922
use function assert;
23+
use function in_array;
2024
use function is_string;
2125
use function iterator_count;
2226
use function iterator_to_array;
@@ -460,11 +464,35 @@ private function isEquivalentIndexKeys(IndexInfo $mongoIndex, array $documentInd
460464
});
461465
}
462466

463-
/* Avoid a strict equality check here. The numeric type returned by
464-
* MongoDB may differ from the document index without implying that the
465-
* indexes themselves are inequivalent. */
467+
/* Avoid a strict equality check of the arrays here. The numeric type returned
468+
* by MongoDB may differ from the document index without implying that the
469+
* indexes themselves are inequivalent. The strict check of the keys asserts
470+
* that the order of the keys remained the same. */
466471
// phpcs:disable SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator
467-
return $mongoIndexKeys == $documentIndexKeys;
472+
return $this->hasTextIndexesAtSamePosition($mongoIndex, $documentIndex) &&
473+
array_keys($mongoIndexKeys) === array_keys($documentIndexKeys) &&
474+
$mongoIndexKeys == $documentIndexKeys;
475+
}
476+
477+
private function hasTextIndexesAtSamePosition(IndexInfo $mongoIndex, array $documentIndex) : bool
478+
{
479+
$mongoIndexKeys = $mongoIndex['key'];
480+
$documentIndexKeys = $documentIndex['keys'];
481+
482+
if (! isset($mongoIndexKeys['_fts']) && ! in_array('text', $documentIndexKeys, true)) {
483+
return true;
484+
}
485+
486+
/*
487+
* We unset _ftsx to avoid the uncertainty whether _fts really comes first and
488+
* therefore denotes the position of the text index.
489+
*/
490+
unset($mongoIndexKeys['_ftsx']);
491+
492+
$mongoIndexTextPosition = array_search('_fts', array_keys($mongoIndexKeys), true);
493+
$documentIndexTextPosition = array_search('text', array_values($documentIndexKeys), true);
494+
495+
return $mongoIndexTextPosition === $documentIndexTextPosition;
468496
}
469497

470498
/**

tests/Doctrine/ODM/MongoDB/Tests/SchemaManagerTest.php

+26-5
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,16 @@ public function dataIsMongoIndexEquivalentToDocumentIndex()
617617
'mongoIndex' => ['key' => ['foo' => 1]],
618618
'documentIndex' => ['keys' => ['foo' => -1]],
619619
],
620+
'compoundIndexKeysSame' => [
621+
'expected' => true,
622+
'mongoIndex' => ['key' => ['foo' => 1, 'baz' => 1]],
623+
'documentIndex' => ['keys' => ['foo' => 1, 'baz' => 1]],
624+
],
625+
'compoundIndexKeysSameDifferentOrder' => [
626+
'expected' => false,
627+
'mongoIndex' => ['key' => ['foo' => 1, 'baz' => 1]],
628+
'documentIndex' => ['keys' => ['baz' => 1, 'foo' => 1]],
629+
],
620630
// Sparse option
621631
'sparseOnlyInMongoIndex' => [
622632
'expected' => false,
@@ -823,34 +833,45 @@ public function dataIsMongoTextIndexEquivalentToDocumentIndex()
823833
],
824834
'compoundIndexKeysSameAndWeightsSame' => [
825835
'expected' => true,
836+
'mongoIndex' => [
837+
'key' => ['a' => -1, '_fts' => 'text', '_ftsx' => 1, 'd' => 1],
838+
'weights' => ['b' => 1, 'c' => 2],
839+
],
840+
'documentIndex' => [
841+
'keys' => ['a' => -1, 'b' => 'text', 'c' => 'text', 'd' => 1],
842+
'options' => ['weights' => ['b' => 1, 'c' => 2]],
843+
],
844+
],
845+
'compoundIndexKeysDifferentOrder' => [
846+
'expected' => false,
826847
'mongoIndex' => [
827848
'key' => ['_fts' => 'text', '_ftsx' => 1, 'a' => -1, 'd' => 1],
828849
'weights' => ['b' => 1, 'c' => 2],
829850
],
830851
'documentIndex' => [
831-
'keys' => ['a' => -1, 'b' => 'text', 'c' => 'text', 'd' => 1],
852+
'keys' => ['a' => -1, 'b' => 'text', 'c' => 'text', 'd' => 1],
832853
'options' => ['weights' => ['b' => 1, 'c' => 2]],
833854
],
834855
],
835856
'compoundIndexKeysSameAndWeightsDiffer' => [
836857
'expected' => false,
837858
'mongoIndex' => [
838-
'key' => ['_fts' => 'text', '_ftsx' => 1, 'a' => -1, 'd' => 1],
859+
'key' => ['a' => -1, '_fts' => 'text', '_ftsx' => 1, 'd' => 1],
839860
'weights' => ['b' => 1, 'c' => 2],
840861
],
841862
'documentIndex' => [
842-
'keys' => ['a' => -1, 'b' => 'text', 'c' => 'text', 'd' => 1],
863+
'keys' => ['a' => -1, 'b' => 'text', 'c' => 'text', 'd' => 1],
843864
'options' => ['weights' => ['b' => 3, 'c' => 2]],
844865
],
845866
],
846867
'compoundIndexKeysDifferAndWeightsSame' => [
847868
'expected' => false,
848869
'mongoIndex' => [
849-
'key' => ['_fts' => 'text', '_ftsx' => 1, 'a' => 1, 'd' => 1],
870+
'key' => ['a' => 1, '_fts' => 'text', '_ftsx' => 1, 'd' => 1],
850871
'weights' => ['b' => 1, 'c' => 2],
851872
],
852873
'documentIndex' => [
853-
'keys' => ['a' => -1, 'b' => 'text', 'c' => 'text', 'd' => 1],
874+
'keys' => ['a' => -1, 'b' => 'text', 'c' => 'text', 'd' => 1],
854875
'options' => ['weights' => ['b' => 1, 'c' => 2]],
855876
],
856877
],

0 commit comments

Comments
 (0)