node.js - 查询 MongoDB 中的本地化数据

标签 node.js mongodb localization aggregation-framework

像这样“本地化”数据:

{
  "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/

相关文章:

node.js - process.argv 在 Node.js 中未定义

javascript - 如何执行条件SQL查询,将结果打包为JSON,并发回客户端?

javascript - 使用socket.io从Mt. Gox的 "now"值获取日期/时间?

java - 我可以将 MongoDB 用于 ActiveMQ 主/从架构吗?

windows - MFC 本地化不适用于 Windows 7 的 MUI 安装

node.js - 安装 screepsmod-mongo 并运行 npx screeps start 后权限被拒绝

java - mongodb java 驱动程序。如何通过引用返回对象

mongodb - 设置 mongoDB 树莓派

winforms - 如何防止编译器为非本地化应用程序创建 appname.resources.dll?

java - 使用本地化对字符串列表进行排序