Files
mongo/jstests/aggregation/sources/graphLookup/collation_graphlookup.js

138 lines
5.6 KiB
JavaScript

/**
* Tests that the $graphLookup stage respects the collation when matching between the
* 'connectFromField' and the 'connectToField'. $graphLookup should use the collation
* set on the aggregation, or the default collation of the collection.
*/
(function() {
"use strict";
var res;
const caseInsensitiveUS = {collation: {locale: "en_US", strength: 2}};
const caseSensitiveUS = {collation: {locale: "en_US", strength: 3}};
var coll = db.collation_graphlookup;
var foreignColl = db.collation_graphlookup_foreign;
// Test that $graphLookup respects the collation set on the aggregation pipeline. Case
// insensitivity should mean that we find both "jeremy" and "jimmy" as friends.
coll.drop();
assert.writeOK(coll.insert({username: "erica", friends: ["jeremy", "jimmy"]}));
assert.writeOK(coll.insert([{username: "JEREMY"}, {username: "JIMMY"}]));
res = coll.aggregate(
[
{$match: {username: "erica"}},
{
$graphLookup: {
from: coll.getName(),
startWith: "$friends",
connectFromField: "friends",
connectToField: "username",
as: "friendUsers"
}
}
],
caseInsensitiveUS)
.toArray();
assert.eq(1, res.length);
assert.eq("erica", res[0].username);
assert.eq(2, res[0].friendUsers.length);
// Negative test: ensure that we don't find any friends when the collation is simple.
res = coll.aggregate([
{$match: {username: "erica"}},
{
$graphLookup: {
from: coll.getName(),
startWith: "$friends",
connectFromField: "friends",
connectToField: "username",
as: "friendUsers"
}
}
])
.toArray();
assert.eq(1, res.length);
assert.eq("erica", res[0].username);
assert.eq(0, res[0].friendUsers.length);
assert.commandWorked(db.runCommand({drop: coll.getName()}));
assert.commandWorked(db.createCollection(coll.getName(), caseInsensitiveUS));
assert.writeOK(coll.insert({username: "erica", friends: ["jeremy", "jimmy"]}));
assert.commandWorkedOrFailedWithCode(db.runCommand({drop: foreignColl.getName()}),
ErrorCodes.NamespaceNotFound);
assert.commandWorked(db.createCollection(foreignColl.getName(), caseSensitiveUS));
assert.writeOK(foreignColl.insert([{username: "JEREMY"}, {username: "JIMMY"}]));
// Test that $graphLookup inherits the default collation of the collection on which it is run,
// and that this collation is used instead of the default collation of the foreign collection.
res = coll.aggregate([
{$match: {username: "erica"}},
{
$graphLookup: {
from: foreignColl.getName(),
startWith: "$friends",
connectFromField: "friends",
connectToField: "username",
as: "friendUsers"
}
}
])
.toArray();
assert.eq(1, res.length);
assert.eq("erica", res[0].username);
assert.eq(2, res[0].friendUsers.length);
// Test that we don't use the collation to dedup string _id values. This would cause us to miss
// nodes in the graph that have distinct _id values which compare equal under the collation.
coll.drop();
assert.writeOK(coll.insert({username: "erica", friends: ["jeremy"]}));
assert.writeOK(coll.insert({_id: "foo", username: "JEREMY", friends: ["jimmy"]}));
assert.writeOK(coll.insert({_id: "FOO", username: "jimmy", friends: []}));
res = coll.aggregate(
[
{$match: {username: "erica"}},
{
$graphLookup: {
from: coll.getName(),
startWith: "$friends",
connectFromField: "friends",
connectToField: "username",
as: "friendUsers"
}
}
],
caseInsensitiveUS)
.toArray();
assert.eq(1, res.length);
assert.eq("erica", res[0].username);
assert.eq(2, res[0].friendUsers.length);
// Test that the result set is not deduplicated under the collation. If two documents are
// entirely equal under the collation, they should still both get returned in the "as" field.
coll.drop();
assert.writeOK(coll.insert({username: "erica", friends: ["jeremy"]}));
assert.writeOK(coll.insert({_id: "foo", username: "jeremy"}));
assert.writeOK(coll.insert({_id: "FOO", username: "JEREMY"}));
res = coll.aggregate(
[
{$match: {username: "erica"}},
{
$graphLookup: {
from: coll.getName(),
startWith: "$friends",
connectFromField: "friends",
connectToField: "username",
as: "friendUsers"
}
}
],
caseInsensitiveUS)
.toArray();
assert.eq(1, res.length);
assert.eq("erica", res[0].username);
assert.eq(2, res[0].friendUsers.length);
})();