像这样“本地化”数据:
{
"cs": [
{
"cID": "00001",
"title": {
"en": "title en1",
"de": "title de1"
},
"desc": {
"en": "desc en1",
"de": "desc de1"
},
"startDate": 20210801,
"endDate": 20210809,
"numDays": 8
},
{
"cID": "00002",
"title": {
"en": "title en2",
"de": "title de2"
},
"desc": {
"en": "desc en2",
"de": "desc de2"
},
"startDate": 20210701,
"endDate": 20210715,
"numDays": 14
}
]
}
考虑用户区域设置(作为参数传递给查询)来查询此问题的最佳方法是什么?例如,如果传递了“en”,则查询应返回“cID”:“00001”:
{
"cID": "00001",
"title": "title en1",
"desc": "desc en1",
"startDate": 20210801,
"endDate": 20210809,
"numDays": 8
}
理想情况下,查询应该是“通用”的,而不是专门过滤“标题”和“描述”对象。
我知道:
db.cs.find({
"cID": "00001"
},
{
"_id": 0,
"cID": 1,
"title": "$title.en",
"desc": "$desc.en",
"startDate": 1,
"endDate": 1,
"numDays": 1
})
会给我:
[
{
"cID": "00001",
"desc": "desc en1",
"endDate": 2.0210809e+07,
"numDays": 8,
"startDate": 2.0210801e+07,
"title": "title en1"
}
]
但是在不同的查询中使用许多语言环境和不同的数据模型来处理它会很棘手。
Mongo Playground :https://mongoplayground.net/p/9erh-VYiOO4
最佳答案
要创建通用查询,需要聚合框架,因为它有一些方便的运算符来帮助您完成此操作。首先,您需要将嵌入文档转换为键/值对数组,然后在传入区域设置作为参数的键字段上过滤该数组。
例如转换文档
"title": {
"en": "title en2",
"de": "title de2"
},
到数组
"title": [
{ "k": "en", '"v": "title en2" },
{ "k": "de", "v": "title de2" }
],
使用 $objectToArray
运算符(operator)。然后,您可以使用 $filter
在关键字段上过滤此数组。运算符为
{
'$filter': {
'input': { '$objectToArray': '$title' },
'cond': { '$eq': ['$$this.k', locale] }
}
}
其中变量区域设置是从传递的参数派生的。
获得过滤后的数组后,获取值字段需要 $arrayElemAt
应用于值键的运算符为
{
'$arrayElemAt': ['$title.v', 0]
}
所以最后你必须运行这样的管道:
var locale = 'en';
db.cs.aggregate([
{ '$match': { "cID" : "00001" } },
{ '$addFields': {
'title': {
'$filter': {
'input': { '$objectToArray': '$title' },
'cond': { '$eq': ['$$this.k', locale] }
}
},
'desc': {
'$filter': {
'input': { '$objectToArray': '$desc' },
'cond': { '$eq': ['$$this.k', locale] }
}
}
} },
{ '$addFields': {
'title': {
'$arrayElemAt': ['$title.v', 0]
},
'desc': {
'$arrayElemAt': ['$desc.v', 0]
}
} }
]);
并进行一些重构:
var locale = 'en';
var getFilterOperatorExpression = function (field) {
return {
'$filter': {
'input': { '$objectToArray': '$'+ field },
'cond': { '$eq': ['$$this.k', locale] }
}
}
};
var getValueOperatorExpression = function (field) {
return {
'$arrayElemAt': ['$'+ field +'.v', 0]
}
};
db.cs.aggregate([
{ '$match': { "cID" : "00001" } },
{ '$addFields': {
'title': getFilterOperatorExpression('title'),
'desc': getFilterOperatorExpression('desc'),
} },
{ '$addFields': {
'title': getValueOperatorExpression('title'),
'desc': getValueOperatorExpression('desc')
} }
]);
关于node.js - 查询 MongoDB 中的本地化数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64742175/