如何计算包含数组中值的文档?
Posted
技术标签:
【中文标题】如何计算包含数组中值的文档?【英文标题】:How do I count the documents that include a value within an array? 【发布时间】:2021-01-03 10:56:52 【问题描述】:我有一个 Mongoose abTest
文档,它有两个字段:
status
。这是一个字符串枚举,类型可以是active
、inactive
或draft
。
validCountryCodes
。这是一个字符串枚举数组(GB
、EU
、AU
等)。默认为空。
在数据库中,在任何时候,我只希望每个validCountryCode
有一个活动的abTest
,因此我在创建或编辑新的abTest
之前执行一些验证。
为此,我编写了一个函数来尝试计算具有status
的active
和包含countryCodes
之一的文档的数量。
如果计数大于一,该函数将返回。如果是这样,我会抛出一个验证错误。
if (params.status === 'active')
const activeTestForCountryExists = await checkIfActiveAbTestForCountry(
validCountryCodes,
);
if (params.activeTestForCountryExists)
throw new ValidationError(
message: 'There can only be one active test for each country code.',
);
const abTest = await AbTest.create(params);
checkIfActiveAbTestForCountry()
看起来像这样:
const checkIfActiveAbTestForCountry = async countryCodes =>
const query =
status: 'active',
;
if (
!countryCodes ||
(Array.isArray(countryCodes) && countryCodes.length === 0)
)
query.validCountryCodes =
$eq: [],
;
else
query.validCountryCodes = $in: [countryCodes] ;
const count = await AbTest.countDocuments(query);
return count > 0;
;
count 查询不仅应该计算完全匹配的数组,还应该计算任何部分匹配。
如果在 DB 中有一个 active
abTest
和一个 validCountryCodes
数组 ['GB', 'AU',]
,则尝试使用 ['GB'
创建一个新的 abTest
应该会失败。因为已经有一个使用GB
作为validCountryCode
的测试。
同样,如果有一个带有validCountryCodes
数组['AU']
的测试,那么创建一个带有['AU,'NZ']
的validCountryCodes
的测试也应该失败。
目前都没有强制执行。
我该怎么做?这可以写一个查询来检查吗?
我考虑过迭代 params.validCountryCodes
并计算包含每个文档的文档,但这似乎是一种不好的做法。
【问题讨论】:
【参考方案1】:看看这个 MongoDB documantation。
据我了解,您需要找出是否有任何文档至少包含指定的countryCodes
之一并且它具有active
状态。那么您的查询应该如下所示:
status: 'active',
$or: [
validCountryCodes: countryCodes[0] ,
validCountryCodes: countryCodes[1] ,
// ...
]
请注意,计数文档并不是检查文档是否存在的有效方式,而是使用 findOne
并仅投影一个字段。
【讨论】:
如果我这样做,那么带有validCountryCodes
或['AU','GB']
的文档将与['GB']
不匹配。应该!
如果您有这样的文档:status: 'active', validCountryCodes: ['AU','GB']
它将匹配此查询 status: 'active', validCountryCodes: 'GB'
`
真的!但是通过checkIfActiveAbTestForCountry
传入的参数是countryCodes
的数组,所以我本质上是在计算至少有一个共同元素的文档
@judgejab 我已经更新了答案,你可以使用循环来构建$or
数组【参考方案2】:
您正在使用正确的 mongo-query 来满足您的要求。您能否验证从您的应用程序执行的实际查询是否相同?检查here
status: 'active', validCountryCodes: $in: [ countryCodes ]
例如;以下查询:
status: 'active', validCountryCodes: $in: ['GB' ]
应该匹配文档:
status: 'active', validCountryCodes: ['AU','GB']
【讨论】:
以上是关于如何计算包含数组中值的文档?的主要内容,如果未能解决你的问题,请参考以下文章