查找包含仅包含特定值而没有其他值的数组字段的文档

时间:2020-11-12 15:12:38

标签: mongodb mongoose

考虑此收藏集:

{
  { name: 'first', toys: ['doll', 'car', 'doll'],
  { name: 'second', toys: ['doll', 'car'],
  { name: 'third', toys: ['doll', 'car', 'bricks'],
  { name: 'fourth', toys: ['doll', 'bricks'],
  { name: 'fifth', toys: []
}

我想查询toys字段是仅包含dollcar的数组的文档。在这种情况下,firstsecond应该匹配。 first之所以匹配,是因为dollcar可以在数组中重复,third不匹配,因为数组中必须没有其他值,并且{{1} }和fourth不匹配,因为它们不同时包含fifthdoll

使用car$all对我不起作用,因为它们与$in相匹配。我该如何实现?谢谢!

2 个答案:

答案 0 :(得分:2)

一种更好的方法是使用聚合运算符$setEquals,该运算符比较两个或多个数组,如果它们具有相同的不同元素,则返回true,否则返回false:

db.collection.find({
    '$expr': { 
        '$setEquals': ['$toys', ['doll', 'car']] 
    }
})

另一种选择是$setDifference,它采用两个数组并相对于第一个数组执行第二个数组的相对补数,并且此操作不需要元素顺序。

在您的情况下,请使用$setDifference中的结果来检查其是否为空并将其设置为查询的基础。

例如操作

{ $setDifference: [ ['doll', 'car', 'doll'], ['doll', 'car'] ] } => []

还有这个

{ $setDifference: [ ['car', 'doll', 'doll'], ['doll', 'car'] ] } => []

以及

{ $setDifference: [ ['car', 'doll'], ['doll', 'car'] ] } => []

{ $setDifference: [ ['doll', 'car'], ['doll', 'car'] ] } => []

但是

{ $setDifference: [ ['doll', 'car', 'bricks'], ['doll', 'car'] ] } => ['bricks']

使用上面的逻辑,作为帮助者,您可以使用$size来获取数组结果的长度,并使用$expr来检查查询表达式的长度是否为0


最终查询:

db.collection.find({
    '$expr': {
        '$eq': [
            { '$size': { 
                '$setDifference': [ 
                    '$toys', 
                    ['doll', 'car'] 
                ] 
            } },
            0
        ]
    }
})

答案 1 :(得分:0)

以下查询检索文档是否具有cardoll或两者都有。但是它不会检索空数组记录。

db.getCollection('toys').find({
    $and: [{
        toys: {$elemMatch: {$in: ["doll", "car"]}}
    },
    {
        toys: {$not: {$elemMatch: {$nin: ["doll", "car"]}}}
    }]})