我试图找到MongoDB中某个子文档的所有唯一字符串,只要其中至少一个包含某个子字符串。 但这些字符串是本地化的。 我想获得所有可能语言的结果。
所以,我的文档看起来像这样:
{
...
"myLocalizedField": {
"en": ...,
"de": ...,
"cz": ...
...
}
我不知道数据库中使用哪些语言,并且并非所有文档都使用相同的语言。
这就是我当前的管道:
[
{
$match:
{
"I DON'T KNOW": {
$regex: "my substring",
},
},
},
{
$project:
{
myLocalizedField: 1,
},
},
{
$unwind:
{
path: "$myLocalizedField",
},
},
{
$group:
{
_id: {
key: "I DON'T KNOW",
},
},
},
]
我不确定在
$match
和 $group
阶段要放什么...
您可以使用 $objectToArray 运算符:
INPUT:
{"en":"foo", "de":"bar", "cz":"buz"}
OUTPUT:
[{"k":"en", "v":"foo"}, {"k":"de", "v":"bar"}, {"k":"cz", "v":"buz"}]
db.collection.aggregate([
{
"$addFields": {
"tmp": {
"$objectToArray": "$myLocalizedField"
}
}
},
{
$match: {
"tmp.v": {
$regex: "llo"
}
}
},
{
$unwind: {
path: "$tmp"
}
},
{
$match: {
"tmp.v": {
$regex: "llo"
}
}
}
])
注意: 此解决方案无法扩展,因为我们在搜索之前重塑了文档。
我建议您以这种方式存储您的文档:
{
"myLocalizedField": [
{"k": "en", "v": "Hello world"},
{"k": "de", "v": "Hallo Welt"},
{"k": "cz", "v": "Ahoj světe"},
{"k": "es", "v": "Hola Mundo"},
]
}
通过这种方式,搜索是可扩展的,并且更容易应用过滤器。
$objectToArray
来救援:
[
{
$project: { localized: { $objectToArray: "$myLocalizedField" } }
},
{
$unwind:
{
path: "$localized",
},
},
{
$match:
{
"localized.v": {
$regex: "my substring",
},
},
},
{
$group:
{
_id: {
key: "$localized.k",
},
},
},
]
我推荐这个:
db.collection.aggregate([
{ $set: { myLocalizedField: { $objectToArray: "$myLocalizedField" } } },
{ $match: { "myLocalizedField.v": { $regex: "llo" } } },
{
$set: {
myLocalizedField: {
$filter: {
input: "$myLocalizedField",
cond: { $regexMatch: { input: "$$this.v", regex: "llo" } }
}
}
}
},
{ $set: { myLocalizedField: { $arrayToObject: "$myLocalizedField" } } }
])
它应该比其他解决方案更快,使用
$unwind
后跟 $group
有点毫无意义。
如您所见,它使用两个正则表达式检查。第一个过滤表达式根本不存在的所有文档,第二个过滤字符串匹配的数组元素。