我有一个看起来像这样的文件:
"tokens":
[
{
"index": 1,
"word": "I",
"pos": "NNP",
},
{
"index": 2,
"word": "played",
"pos": "VBZ",
},
{
"index": 3,
"word": "football",
"pos": "IN",
}
]
我的疑问是:
db.test.find({
$and: [
{
'tokens.word': 'I'
},
{
tokens: {
$elemMatch: {
word: /f.*/,
pos: 'IN'
}
}
}
]
})
我的查询输出是上面的文档。但是在这种情况下结果应该是不匹配的,因为我正在搜索
字:“我”后跟 [字:/f.*/和pos:'IN']
与文档中的tokens
数组不匹配,因为令牌I
后跟played
,然后是football
。但是,在查询中,过滤器的顺序不同,因为使用
字:“我”
接着是
F。*
[足球在这种情况下]。
答案 0 :(得分:0)
$and
运算符是纯逻辑运算符,其中过滤条件的顺序不起任何作用。
因此,从结果集的角度来看,以下查询绝对等效:
$and: [
{ "a": 1 },
{ "b": 2 }
]
$and: [
{ "b": 2 },
{ "a": 1 }
]
$并对两个或更多的数组执行逻辑AND运算 表达式(例如,等)并选择 满足数组中所有表达式的文档。 $和 操作员使用短路评估。如果是第一个表达式(例如 )评估为false,MongoDB不会评估 剩下的表达。
在您的示例中,"index1"
条目与第一个过滤器"tokens.word": "I"
匹配,"index3"
文档与第二个$elemMatch
过滤器匹配。所以文件必须返回。
<强>更新强>
这是一个想法 - 更多的是一个真正的起点 - 让你更接近你想要的东西:
db.collection.aggregate({
$addFields: { // create a temporary field
"differenceBetweenMatchPositions": { // called "differenceBetweenMatchPositions"
$subtract: [ // which holds the difference between
{ $indexOfArray: [ "$tokens.word", "I" ] }, // the index of first element matching first condition and
{ $min: { // the lowest index of
$filter: { // a filtered array
input: { $range: [ 0, { $size: "$tokens" } ] }, // that holds the indices [ 0, 1, 2, ..., n ] where n is the number of items in the "tokens" array - 1
as: "this", // which we want to access using "$$this"
cond: {
$let: {
vars: { "elem": { $arrayElemAt: [ "$tokens", "$$this" ] } }, // get the n-th element in our "tokens" array
in: {
$and: [
{ $eq: [ "$$elem.pos", "IN" ] }, // "pos" field must be "IN"
{ $eq: [ { $substrBytes: [ "$$elem.word", 0, 1 ] }, "f" ] } // 1st character of the "word" must be "f"
]
}
}
}
}
}
}]
}
}
}, {
$match: {
"differenceBetweenMatchPositions": { $lt: 0 } // we only want documents where the first condition is matched by an item in our array before the second one gets matched, too.
}
})