我有一份文件,其中包含以下文件:
{ "f" : [ [ 1, 2, 3], [4, 5, 6] ] } // should match because of [1, 2, 3]
{ "f" : [ [ 2, 1, 3], [4, 5, 6] ] } // should match because of [2, 1, 3]
{ "f" : [ [ 1, 2, 4], [4, 5, 6] ] } // should NOT match
在这个集合中,我希望匹配文档,这些文档在" f"的一个数组中包含一个包含1,2和3的数组。字段。
到目前为止我已尝试过:
db.mytest.find({ f: { $elemMatch: { $all: [1,2,3] } } } )
我希望这个查询有效,但我不明白为什么不这样做。我不匹配任何文件。
db.mytest.find({ f: { $elemMatch: { $elemMatch: { $all: [1,2,3] } } } })
这也行不通。
db.mytest.find({ f: { $all: [[1,2,3]] } })
这可行,但元素必须按照确切的顺序排列。我希望能够匹配输入数组也是2,1,3。一种可能的解决方案必须是始终按升序存储元素并使用此查询。
db.mytest.find({ f: { $elemMatch: { $elemMatch: { $in: [1, 2, 3] } } } })
这有效但它匹配包含1,2或3中任何一个的所有文档。我只想要在单个数组中包含正好1,2和3的文档。
我在寻找什么查询?
答案 0 :(得分:2)
似乎运算符在嵌入式数组的情况下执行精确匹配。不是最令人满意或最佳的解决方案(您需要使用集合中的记录对其进行测试),但一种方法是通过服务器端的聚合管道进行测试。
Project
每个文件的额外字段代表" f"值。unwind
实际的" f"字段,以便我们可以匹配单个数组
元件。match
文件" f"包含输入中的所有值
阵列。project
返回原始文档的临时字段。代码:
db.mytest.aggregate([
{$project:{"temp":"$f","f":1}}, // maintain a temporary variable for projection
{$unwind:"$f"}, // f:[1,2,3] f:[4,5,6] become separate records.
{$match:{"f":{$all:[1,2,3]}}}, // use $all to match all the elements.
{$project:{"f":"$temp"}} // project the temporary variable.
])
答案 1 :(得分:1)
您正在查找f
包含[1, 2, 3]
的文档。试试db.mytest.find({f: {$in: [[1, 2, 3]]}})
。
不幸的是,找到所有可能排列的最简单方法是在程序中构建它们(如果您使用的是Python,itertools.permutations
将为您执行此操作)并更改$in
查询到[[1, 2, 3], [2, 1, 3], ...]
。很糟糕。
答案 2 :(得分:1)
如何生成数组的所有排列并在查询中使用?像这样的东西:
db.mytest.find({$or : [{f: {$all : [[1,2,3]] }}, {f: {$all : [[2,1,3]]}}, {f: {$all: [[3,1,2]]}}]})
也许这不是有效的方式。