我的问题有两部分。我的文档结构如下。
-
我主要想查询数组
foo.*.bar.*
的项。如果每个文档的foo
(即bar
的父级(的键不同,我如何在查询中访问bar
? -
特别地,
bar
是可变长度的阵列。bar
可以保存的项目来自固定集合(例如cat
、dog
、cow
等(。bar
可能有任意数量的,按任意顺序排列的。我想查询:只有一个bar
的文档,该文档包含一个或多个特定项目。例如CCD_ 12=>它将返回文档#2。(即使它在一个bar
中有两个cats
,但它只有一个带有cats
的bar
为了更清楚地说明这一点,下面是谓词的伪代码:I
predictate(document, item):
bars_which_contain_item = 0
foreach currentFoo in document.foo:
if currentFoo.bar.contains(item) bars_which_contain_item += 1
return bars-which-contain-item == 1;
我看过关于查询数组、嵌入文档和嵌入文档数组的文档,但找不到答案。我想做的事情有可能吗?或者,我需要添加一个遍历我的所有数据并添加numberOfCats、numberofDogs、numberOfCows字段的过程,以便将来进行这种查询吗?(我不需要经常进行这种查询,性能也不太重要(。
附言:我使用的是nodejs,但我想查询结构不会有太大变化。(此外,如果我能在MongoDB Compass中进行查询,那就更好了(。
{ _id: 1, foo: { a : { bar: ['cat', 'dog', 'cow'] }, b : { bar: ['cat', 'cat', 'dog'] }, } }, { _id: 2, foo: { c : { bar: ['cow'] }, d : { bar: ['dog'] }, e : { bar: ['cow'] }, f : { bar: ['cat', 'dog', 'cat'] }, } }, { _id: 3, foo: { g : { bar: ['cat', 'cow'] }, h : { bar: ['cow'] }, i : { bar: ['cat'] }, } }
对于第一个问题,使用https://docs.mongodb.com/manual/reference/operator/aggregation/objectToArray/.
r = db.foo.aggregate([
{$project: {foo: {$objectToArray: '$foo'}}},
{$project: {foo: '$foo.v'}},
])
# =>
{"_id":1,"foo":[{"bar":["cat","dog","cow"]},{"bar":["cat","cat","dog"]}]}
{"_id":2,"foo":[{"bar":["cow"]},{"bar":["dog"]},{"bar":["cow"]},{"bar":["cat","dog","cat"]}]}
{"_id":3,"foo":[{"bar":["cat","cow"]},{"bar":["cow"]},{"bar":["cat"]}]}
对于您的第二个问题:
r = db.foo.aggregate([
{$project: {foo: {$objectToArray: '$foo'}}},
{$project: {foo: '$foo.v'}},
{$project: {foo: {$cond: {
if: {eq: ['cat', '$foo.bar']},
then: '$foo.bar',
else: '$$REMOVE',
}}}},
{$project: {foo: {$filter: {
input: '$foo',
as: 'x',
cond: {$in: ['cat', '$$x']},
}}}},
{$match: {foo: {$size: 1}}},
])
{"_id":2,"foo":[["cat","dog","cat"]]}