summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Suarez <kyle.suarez@mongodb.com>2017-09-20 14:31:17 -0400
committerKyle Suarez <kyle.suarez@mongodb.com>2017-09-20 14:31:17 -0400
commit7a15db88968b9f6dd4418f4a89a2826c82b2ecac (patch)
tree7ee7b58ac2ace0609561c3c1467c0dded2753a5e
parent77bbdee3f8b59b1e070129616360f87e190a540b (diff)
downloadmongo-7a15db88968b9f6dd4418f4a89a2826c82b2ecac.tar.gz
SERVER-30695 uniqueItems must ignore field order when comparing documents
-rw-r--r--jstests/core/json_schema/unique_items.js8
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_unique_items.h9
-rw-r--r--src/mongo/db/matcher/schema/expression_internal_schema_unique_items_test.cpp6
3 files changed, 16 insertions, 7 deletions
diff --git a/jstests/core/json_schema/unique_items.js b/jstests/core/json_schema/unique_items.js
index f94fb5546d8..08c8ae84211 100644
--- a/jstests/core/json_schema/unique_items.js
+++ b/jstests/core/json_schema/unique_items.js
@@ -41,10 +41,8 @@
assertSchemaMatch(coll, schema, {a: [{a: 1}, {a: 1}]}, false);
assertSchemaMatch(coll, schema, {a: [[1, 2], [1, 2]]}, false);
assertSchemaMatch(coll, schema, {a: [null, null]}, false);
-
- // TODO (SERVER-30695): uniqueItems should compare objects in a field order-insensitive way when
- // testing for uniqueness.
- assertSchemaMatch(coll, schema, {a: [{x: 1, y: 1}, {y: 1, x: 1}]}, true);
+ assertSchemaMatch(coll, schema, {a: [{x: 1, y: 1}, {y: 1, x: 1}]}, false);
+ assertSchemaMatch(coll, schema, {a: [{x: [1, 2], y: "a"}, {y: "a", x: [1, 2]}]}, false);
// Test that {uniqueItems: false} has no effect.
schema = {properties: {a: {uniqueItems: false}}};
@@ -60,4 +58,6 @@
assertSchemaMatch(coll, schema, {a: [{a: 1}, {a: 1}]}, true);
assertSchemaMatch(coll, schema, {a: [[1, 2], [1, 2]]}, true);
assertSchemaMatch(coll, schema, {a: [null, null]}, true);
+ assertSchemaMatch(coll, schema, {a: [{x: 1, y: 1}, {y: 1, x: 1}]}, true);
+ assertSchemaMatch(coll, schema, {a: [{x: [1, 2], y: "a"}, {y: "a", x: [1, 2]}]}, true);
}());
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.h b/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.h
index 570cf448f07..07beff92319 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.h
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.h
@@ -30,13 +30,16 @@
#include <utility>
-#include "mongo/bson/bsonelement_comparator.h"
+#include "mongo/bson/unordered_fields_bsonelement_comparator.h"
#include "mongo/db/matcher/expression_array.h"
namespace mongo {
/**
- * Matches arrays whose elements are all unique.
+ * Matches arrays whose elements are all unique. When comparing elements,
+ *
+ * - strings are always compared using the "simple" string comparator; and
+ * - objects are compared in a field order-independent manner.
*/
class InternalSchemaUniqueItemsMatchExpression final : public ArrayMatchingMatchExpression {
public:
@@ -81,6 +84,6 @@ public:
private:
// The comparator to use when comparing BSONElements, which will never use a collation.
- BSONElementComparator _comparator{BSONElementComparator::FieldNamesMode::kIgnore, nullptr};
+ UnorderedFieldsBSONElementComparator _comparator;
};
} // namespace mongo
diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_unique_items_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_unique_items_test.cpp
index 16628681ae1..5e9d1a119b4 100644
--- a/src/mongo/db/matcher/schema/expression_internal_schema_unique_items_test.cpp
+++ b/src/mongo/db/matcher/schema/expression_internal_schema_unique_items_test.cpp
@@ -64,6 +64,7 @@ TEST(InternalSchemaUniqueItemsMatchExpression, MatchesArrayOfUniqueItems) {
ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: [1, 'bar', {}, [], null]}")));
ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: [{x: 1}, {x: 2}, {x: 2, y: 3}]}")));
ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: [[1], [1, 2], 1]}")));
+ ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: [['a', 'b'], ['b', 'a']]}")));
}
TEST(InternalSchemaUniqueItemsMatchExpression, MatchesNestedArrayOfUniqueItems) {
@@ -72,6 +73,7 @@ TEST(InternalSchemaUniqueItemsMatchExpression, MatchesNestedArrayOfUniqueItems)
ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: {bar: [1, 'bar', {}, [], null]}}")));
ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: {bar: [{x: 1}, {x: 2}, {x: 2, y: 3}]}}")));
ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: {bar: [[1], [1, 2], 1]}}")));
+ ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: {bar: [['a', 'b'], ['b', 'a']]}}")));
}
TEST(InternalSchemaUniqueItemsMatchExpression, RejectsArrayWithDuplicates) {
@@ -79,6 +81,8 @@ TEST(InternalSchemaUniqueItemsMatchExpression, RejectsArrayWithDuplicates) {
ASSERT_OK(uniqueItems.init("foo"));
ASSERT_FALSE(uniqueItems.matchesBSON(fromjson("{foo: [1, 1, 1]}")));
ASSERT_FALSE(uniqueItems.matchesBSON(fromjson("{foo: [['bar'], ['bar']]}")));
+ ASSERT_FALSE(
+ uniqueItems.matchesBSON(fromjson("{foo: [{x: 'a', y: [1, 2]}, {y: [1, 2], x: 'a'}]}")));
}
TEST(InternalSchemaUniqueItemsMatchExpression, RejectsNestedArrayWithDuplicates) {
@@ -86,6 +90,8 @@ TEST(InternalSchemaUniqueItemsMatchExpression, RejectsNestedArrayWithDuplicates)
ASSERT_OK(uniqueItems.init("foo"));
ASSERT_FALSE(uniqueItems.matchesBSON(fromjson("{foo: {bar: [1, 1, 1]}}")));
ASSERT_FALSE(uniqueItems.matchesBSON(fromjson("{foo: {bar: [['baz'], ['baz']]}}")));
+ ASSERT_FALSE(uniqueItems.matchesBSON(
+ fromjson("{foo: {bar: [{x: 'a', y: [1, 2]}, {y: [1, 2], x: 'a'}]}}")));
}
TEST(InternalSchemaUniqueItemsMatchExpression, FieldNameSignificantWhenComparingNestedObjects) {