Попробуйте этот запрос:
db.collection.aggregate([
/** First match stage is optional if all of your docs are of type array & not empty */
{ $match: { $expr: { $and: [{ $eq: [{ $type: "$library" }, "array"] }, { $ne: ["$library", []] }] } } },
/** Add a new field allUnique to each doc, will be false where if elements in library have duplicates */
{
$addFields: {
allUnique: {
$eq: [
{
$size:
{
$reduce: {
input: "$library.serialNumber",
initialValue: [], // start with empty array
/** iterate over serialNumber's array from library & push current value if it's not there in array, at the end reduce would produce an array with uniques */
in: { $cond: [{ $in: ["$$this", "$$value"] }, [], { $concatArrays: [["$$this"], "$$value"] }] }
}
}
},
{
$size: "$library"
}
]
}
}
},
/** get docs where allUnique: false */
{
$match: {
allUnique: false
}
},
/** Project only needed fields & remove _id which is bydefault projected */
{
$project: {
userName: 1,
_id: 0
}
}
])
Другой вариант может сделать это через $unwind
, но это не является предпочтительным для огромных наборов данных, поскольку это взрывает вашу коллекцию.
Тест : MongoDB-Playground
Или из ответа @Dennis по этой ссылке дубликаты-записи-из-массива , вы можете попробовать, как показано ниже:
db.collection.aggregate([
{
$match: {
$expr: {
$and: [
{
$eq: [
{
$type: "$library"
},
"array"
]
},
{
$ne: [
"$library",
[]
]
}
]
}
}
},
{
$addFields: {
allUnique: {
$eq: [
{
$size: {
"$setUnion": [
"$library.serialNumber",
[]
]
}
},
{
$size: "$library"
}
]
}
}
},
{
$match: {
allUnique: false
}
},
{
$project: {
userName: 1,
_id: 0
}
}
])
Тест: MongoDB-Playground