【问题标题】:MongoDB query on multiple array of objectsMongoDB查询多个对象数组
【发布时间】:2020-10-30 22:09:36
【问题描述】:

假设我有一个 user 的 mongoSchema,具有以下字段

googleId: String,
name: String,
Language : [{}],

用户最初可以在他们的个人资料页面上指定一组语言集 [最多 5 个]。

例如,用户可以有两种语言设置如下:

语言:

[main: {name: English, code: ko}, secondary: [{name:Japanese, code: jp}, {name:Chinese, code: en}]], 

[main: {name: Korean, code: ko}, secondary: [{name:Japanese, code: jp}, {name:English, code: en}]

根据这些信息,我只想呈现符合以下偏好的帖子。

例如用 EnglishJapaneseEnglishChinese 的帖子(从第一个语言集开始)

以及用韩语日语韩语英语的帖子(来自第二语言集)

我的帖子架构有

    postName: String
    original: {},
    target: {},

例如,

postName: 'Korean to Japanese Post'
original: {name: Korean, code: ko}
target: {name: Japanese, code jp}

我应该在大括号内放什么来获取指定语言集的帖子

const prefLang = req.user.Language
const post = await Post.find({ some query using prefLang to check over matching original and target })
res.send(translations)

【问题讨论】:

  • (1.) 字段 Language 的实际架构是否在您的代码中定义?因为main: [Object] 表示对象数组,[Array] 表示数组数组。 (2.) 另外,在您的示例中,secondary 应该有多个对象,对吧?目前您有一个带有重复键的对象。 (3.) 你的帖子架构有原始和目标,但你没有提到user.originaluser.target 那么req.user.originalreq.user.target 是什么?不应该是user.Language吗?
  • 1.抱歉,我打印了 console.log。在模式中,它被定义为 Language: [{}] 2. 是的,它应该是多个 [{name: Japanese, code:jp}, {name:Chinese, code: ch}] 3) 我应该只有 const prefLanguage = req .user.Language。抱歉,我将编辑此信息

标签: node.js mongodb mongoose mongodb-query mern


【解决方案1】:

对于您的示例,查询对象应如下所示

{
  $or: [
    {
      original: { name: "English", code: "en" },
      target: {
        $in: [{ name: "Japanese", code: "jp" }, { name: "Chinese", code: "cn" }]
      }
    },
    {
      original: { name: "Korean", code: "ko" },
      target: {
        $in: [{ name: "Japanese", code: "jp" }, { name: "English", code: "en" }]
      }
    }
  ]
}

所以你必须像这样从prefLang 构造条件

const query = {
  $or: perfLang.map(lang => ({
    original: lang.main,
    target: { $in: lang.secondary }
  }))
}

const post = await Post.find(query)

提示:

如果语言对象有严格的模式,你可以这样定义它们

const LanguageSchema = new mongoose.Schema({
  name: String,
  code: String
}, {
  _id: false
})

const UserSchema = new mongoose.Schema({
  //...
  googleId: String,
  name: String,
  Language: [{ main: LanguageSchema, secondary: [LanguageSchema] }]
})

【讨论】:

    【解决方案2】:

    听起来使用基本布尔逻辑就足够了:

    const prefLang = req.user.Language;
    
    let conditions = [];
    
    prefLang.forEach((langObj) => {
        let tragetLangs = langObj.secondary.map(lang => lang.code);
        conditions.push({
            $and: [
                {
                    "original.code": langObj.main.code,
                },
                {
                    "target.code": {$in: tragetLangs}
                }
            ]
        })
    })
    
    // you should check conditions !== empty array.
    const post = await Post.find({$or: conditions})
    

    【讨论】:

    • 这不是只列出与第一组匹配的帖子吗?我最多可以设置 5 种语言。我想遍历所有这些。
    • 那我误解了数据结构,prefLange是我在评论中指定的那些对象的列表吗?
    • 是的,它是语言集对象的列表。对不起,我没有说清楚
    • 我编辑了我的答案以支持数组,逻辑仍然相似,但我们在构建的条件上执行$or,因为可以有多个。
    • 您不能使用 find 添加自定义排序,即使您使用聚合,您仍然必须手动添加一个占位符字段,如 kr_sort: 1, jp_sort: 2,然后您才能为了对此进行排序,我将添加一个以用户开头的简单聚合来显示它。
    猜你喜欢
    • 2021-09-24
    • 1970-01-01
    • 1970-01-01
    • 2012-05-05
    • 2014-05-13
    • 1970-01-01
    • 2018-07-23
    • 1970-01-01
    • 2020-07-27
    相关资源
    最近更新 更多