summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/core/hashindex1.js10
-rw-r--r--src/mongo/db/index/expression_keys_private.cpp20
2 files changed, 22 insertions, 8 deletions
diff --git a/jstests/core/hashindex1.js b/jstests/core/hashindex1.js
index 49b5cfe7c75..61f98f980f3 100644
--- a/jstests/core/hashindex1.js
+++ b/jstests/core/hashindex1.js
@@ -94,3 +94,13 @@ var total = t.find().hint({"_id": 1}).toArray().length;
var totala = t.find().hint(goodspec).toArray().length;
assert.eq(total, totala, "non-sparse index has wrong total");
assert.lt(totalb, totala, "sparse index should have smaller total");
+
+// Test that having arrays along the path of the index is not allowed.
+assert.commandWorked(t.createIndex({"field1.field2.0.field4": "hashed"}));
+assert.commandFailedWithCode(t.insert({field1: []}), 16766);
+assert.commandFailedWithCode(t.insert({field1: {field2: []}}), 16766);
+assert.commandFailedWithCode(t.insert({field1: {field2: {0: []}}}), 16766);
+assert.commandFailedWithCode(t.insert({field1: [{field2: {0: []}}]}), 16766);
+assert.commandFailedWithCode(t.insert({field1: {field2: {0: {field4: []}}}}), 16766);
+assert.commandWorked(t.insert({field1: {field2: {0: {otherField: []}}}}));
+assert.commandWorked(t.insert({field1: {field2: {0: {field4: 1}}}}));
diff --git a/src/mongo/db/index/expression_keys_private.cpp b/src/mongo/db/index/expression_keys_private.cpp
index 11ed573f27f..cd170c24819 100644
--- a/src/mongo/db/index/expression_keys_private.cpp
+++ b/src/mongo/db/index/expression_keys_private.cpp
@@ -346,7 +346,18 @@ void ExpressionKeysPrivate::getHashKeys(const BSONObj& obj,
const CollatorInterface* collator,
BSONObjSet* keys) {
const char* cstr = hashedField.c_str();
- BSONElement fieldVal = dps::extractElementAtPath(obj, cstr);
+ BSONElement fieldVal = dps::extractElementAtPathOrArrayAlongPath(obj, cstr);
+
+ // If we hit an array while traversing the path, 'cstr' will point to the path component
+ // immediately following the array, or the null termination byte if the final field in the path
+ // was an array.
+ uassert(
+ 16766,
+ str::stream()
+ << "Error: hashed indexes do not currently support array values. Found array at path: "
+ << hashedField.substr(
+ 0, hashedField.size() - StringData(cstr).size() - !StringData(cstr).empty()),
+ fieldVal.type() != BSONType::Array);
// Convert strings to comparison keys.
BSONObj fieldValObj;
@@ -355,13 +366,6 @@ void ExpressionKeysPrivate::getHashKeys(const BSONObj& obj,
CollationIndexKey::collationAwareIndexKeyAppend(fieldVal, collator, &bob);
fieldValObj = bob.obj();
fieldVal = fieldValObj.firstElement();
- }
-
- uassert(16766,
- "Error: hashed indexes do not currently support array values",
- fieldVal.type() != Array);
-
- if (!fieldVal.eoo()) {
BSONObj key = BSON("" << makeSingleHashKey(fieldVal, seed, hashVersion));
keys->insert(key);
} else if (!isSparse) {