为什么查询文档使用值“null”错误地匹配子文档数组中的字段?

时间:2014-02-24 17:59:12

标签: mongodb

我正在使用以下查询尝试match a field without specifying an array index

db.games.find( { 'players.userId': userId } )

其中userId是String或null如果没有用户登录。我期望{{1但是我发现情况并非如此 - 计算count()为空数组0的所有文档。我希望userId === null可能是players,但不是[]。这里发生了什么? mongo使用players.userId而非undefined,强制null==是否为相同的值?

1 个答案:

答案 0 :(得分:2)

解释请考虑以下文件:

{ 
    name: "PacMan",
    players: [ { userId: "Bill" }, { userId: "Ted" }, { userId: "Death" } ]
}
{ 
    name: "Frogger", 
    players: [ { userId: null }, { userId: "Bill" }, { userId: null } ] 
}
{
    name: "Defender",
    players: [ ]
}

如果您发出如下查询:

>db.games.find({ "players.userId" : "Bill" })

{ 
    name: "PacMan",
    players: [ { userId: "Bill" }, { userId: "Ted" }, { userId: "Death" } ]
}
{ 
    name: "Frogger", 
    players: [ { userId: null }, { userId: "Bill" }, { userId: null } ] 
}

您将获得您期望的两个文档,其中包含该userId的播放器在数组中。但是,如果我们将其更改为null

>db.games.find({ "players.userId" : null })

{ 
    name: "Frogger", 
    players: [ { userId: null }, { userId: "Bill" }, { userId: null } ] 
}
{
    name: "Defender",
    players: [ ]
}

等一下,你得到一份你没想到的文件。玩家阵列中没有元素。那为什么它匹配?我们来看看这个表格:

>db.games.find({ "players.userId" : {$exists: true } })
{ 
    name: "PacMan",
    players: [ { userId: "Bill" }, { userId: "Ted" }, { userId: "Death" } ]
}
{ 
    name: "Frogger", 
    players: [ { userId: null }, { userId: "Bill" }, { userId: null } ] 
}

现在,我们的结果,其中players.userId字段实际上,并且第三个文档将不会包含在内,因为它没有匹配的项目这种情况。所以最后考虑最后一种形式:

>db.games.find({ $and: [
    {"players.userId" : {$exists: true }}, 
    {"players.userId": null }
] })

{ 
    name: "Frogger", 
    players: [ { userId: null }, { userId: "Bill" }, { userId: null } ] 
}

如果存在字段,则会找到结果,并且其值为null

总结一下。即使数组不包含任何与null值测试匹配的元素,它仍然可能返回,因为null条件被认为是真的,因为空项目的计算结果为{{1} }。如果您想排除这种情况,那么您可以使用$exists来测试首先是否存在该字段。