为什么查询文档使用值`null`错误地匹配子文档数组中的字段? [英] Why does query document erroneously match field in array of subdocuments using value `null`?

查看:80
本文介绍了为什么查询文档使用值`null`错误地匹配子文档数组中的字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过以下查询匹配未指定数组索引的字段:

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

其中,userId是字符串,或者如果没有用户登录,则是null.我希望上述光标的count()userId === null时是0,但是我发现这不是情况-对players为空数组[]的所有文档进行计数.我希望players.userId可能是undefined,但不是null.这里发生了什么? mongo是否使用==而不是===,将undefinednull强制设置为相同的值?

where userId is either a String or is null if no user is logged in. I expect the count() of the above cursor to be 0 when userId === null, but I find that this is not the case -- all documents for which players is an empty array [] are counted. I would expect that players.userId would be undefined perhaps, but not null. What is going on here? Does mongo use == and not ===, coercing undefined and null to be the same value?

推荐答案

要解释,请考虑以下文档:

To explain consider the following documents:

{ 
    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

You will get the two documents you expect that has the player with that userId present in the array. But if we change that to null

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

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

请稍等片刻,您会得到一份您没想到的文档.玩家数组中没有元素.那么为什么匹配呢?让我们看看这种形式:

Wait a minute, you get a document you didn't expect. There are no elements in the players array. So why is it matching? Let's look at this form:

>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字段实际上是 ,并且将不包含第三个文档,因为它没有符合此条件的项目.所以最后考虑最后一种形式:

Now that gives us results only where the players.userId field is actually there, and the third document will not be included as it has no items that match this condition. So finally consider the last form:

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

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

这将找到结果,其中存在一个字段并且该字段具有null值.

This will find the result whsere there is a field present and it has a null value.

所以总结一下.即使数组中不包含任何与null值测试匹配的元素,由于空项目的值为null,因此认为null条件为true,它仍可能返回结果.如果您想排除这种情况,请使用 $存在,以便首先测试该字段的存在.

So to sum up. Even if an array does not contain any elements that would match a null value test it may still return as a result as the null condition is considered to be true as the empty items evaluates to null. If you want to exclude this case then you use $exists in order to test for the presence of the field in the first place.

这篇关于为什么查询文档使用值`null`错误地匹配子文档数组中的字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆