mongo/jstests/core/index/indexu.js

155 lines
4.8 KiB
JavaScript

// @tags: [
// requires_non_retryable_writes,
// requires_getmore,
// ]
// Test index key generation with duplicate values addressed by array index and
// object field. SERVER-2902
const collNamePrefix = "jstests_indexu_";
let collCount = 0;
let t = db.getCollection(collNamePrefix + collCount++);
t.drop();
const dupDoc = {
_id: 0,
a: [{"0": 1}],
}; // There are two 'a.0' fields in this doc.
const dupDoc2 = {
a: [{"1": 1}, "c"],
};
const noDupDoc = {
a: [{"1": 1}],
};
// Test that we can't index dupDoc.
assert.commandWorked(t.save(dupDoc));
assert.commandFailedWithCode(t.createIndex({"a.0": 1}), 16746);
// Test that we can fail gracefully when dupDoc has a large array padded with nulls.
// Index is based on max padding constant in mongo/db/update/path_support.h
assert.commandWorked(t.update({_id: 0}, {$set: {"a.1500001": 1}}));
assert.commandFailedWithCode(t.createIndex({"a.0": 1}), 16746);
t.remove({});
assert.commandWorked(t.createIndex({"a.0": 1}));
assert.writeError(t.save(dupDoc));
// Test that we can't index dupDoc2.
t = db.getCollection(collNamePrefix + collCount++);
t.drop();
assert.commandWorked(t.save(dupDoc2));
assert.commandFailedWithCode(t.createIndex({"a.1": 1}), 16746);
t.remove({});
assert.commandWorked(t.createIndex({"a.1": 1}));
assert.writeError(t.save(dupDoc2));
// Test that we can index dupDoc with a different index.
t = db.getCollection(collNamePrefix + collCount++);
t.drop();
t.createIndex({"a.b": 1});
assert.commandWorked(t.save(dupDoc));
// Test number field starting with hyphen.
t = db.getCollection(collNamePrefix + collCount++);
t.drop();
t.createIndex({"a.-1": 1});
assert.commandWorked(t.save({a: [{"-1": 1}]}));
// Test number field starting with zero.
t = db.getCollection(collNamePrefix + collCount++);
t.drop();
t.createIndex({"a.00": 1});
assert.commandWorked(t.save({a: [{"00": 1}]}));
// Test multiple array indexes
t = db.getCollection(collNamePrefix + collCount++);
t.drop();
t.createIndex({"a.0": 1, "a.1": 1});
assert.commandWorked(t.save({a: [{"1": 1}]}));
assert.writeError(t.save({a: [{"1": 1}, 4]}));
// Test that we can index noDupDoc.
t = db.getCollection(collNamePrefix + collCount++);
t.drop();
t.save(noDupDoc);
assert.commandWorked(t.createIndex({"a.0": 1}));
assert.commandWorked(t.createIndex({"a.1": 1}));
t = db.getCollection(collNamePrefix + collCount++);
t.drop();
t.createIndex({"a.0": 1});
t.createIndex({"a.1": 1});
assert.commandWorked(t.save(noDupDoc));
// Test that we can query noDupDoc.
assert.eq(1, t.find({"a.1": 1}).hint({"a.1": 1}).itcount());
assert.eq(1, t.find({"a.1": 1}).hint({$natural: 1}).itcount());
assert.eq(
1,
t
.find({"a.0": {"1": 1}})
.hint({"a.0": 1})
.itcount(),
);
assert.eq(
1,
t
.find({"a.0": {"1": 1}})
.hint({$natural: 1})
.itcount(),
);
// Check multiple nested array fields.
t = db.getCollection(collNamePrefix + collCount++);
t.drop();
t.save({a: [[1]]});
assert.commandWorked(t.createIndex({"a.0.0": 1}));
assert.eq(1, t.find({"a.0.0": 1}).hint({$natural: 1}).itcount());
assert.eq(1, t.find({"a.0.0": 1}).hint({"a.0.0": 1}).itcount());
// Check where there is a duplicate for a partially addressed field but not for a fully addressed
// field.
t = db.getCollection(collNamePrefix + collCount++);
t.drop();
t.save({a: [[1], {"0": 1}]});
assert.commandFailed(t.createIndex({"a.0.0": 1}));
// Check where there is a duplicate for a fully addressed field.
t = db.getCollection(collNamePrefix + collCount++);
t.drop();
assert.commandWorked(t.save({a: [[1], {"0": [1]}]}));
assert.commandFailedWithCode(t.createIndex({"a.0.0": 1}), 16746);
// Two ways of addressing parse to an array.
t = db.getCollection(collNamePrefix + collCount++);
t.drop();
t.save({a: [{"0": 1}]});
assert.commandFailedWithCode(t.createIndex({"a.0.0": 1}), 16746);
// Test several key depths - with same arrays being found.
t = db.getCollection(collNamePrefix + collCount++);
t.drop();
t.save({a: [{"0": [{"0": 1}]}]});
assert.commandFailedWithCode(t.createIndex({"a.0.0.0.0.0.0": 1}), 16746);
assert.commandFailedWithCode(t.createIndex({"a.0.0.0.0.0": 1}), 16746);
assert.commandFailedWithCode(t.createIndex({"a.0.0.0.0": 1}), 16746);
assert.commandFailedWithCode(t.createIndex({"a.0.0.0": 1}), 16746);
assert.commandFailedWithCode(t.createIndex({"a.0.0": 1}), 16746);
assert.commandFailedWithCode(t.createIndex({"a.0": 1}), 16746);
assert.commandWorked(t.createIndex({"a": 1}));
// Two prefixes extract docs, but one terminates extraction before array.
t = db.getCollection(collNamePrefix + collCount++);
t.drop();
t.save({a: [{"0": {"c": []}}]});
assert.commandFailedWithCode(t.createIndex({"a.0.c": 1}), 16746);
t = db.getCollection(collNamePrefix + collCount++);
t.drop();
t.save({a: [[{"b": 1}]]});
assert.eq(1, t.find({"a.0.b": 1}).itcount());
t.createIndex({"a.0.b": 1});
assert.eq(1, t.find({"a.0.b": 1}).itcount());