如何在MongoDB中通过Object.keys过滤文档

enyaitl3  于 2023-04-05  发布在  Go
关注(0)|答案(1)|浏览(142)

我想在MongoDB中根据文档对象的键来过滤文档,就像javascript中的这个例子:

const collection = [
  {
    "emailsandnames": {
       "john@email.tld": "john"
    }
  }, 
  {
    "emailsandnames": {
        "doe@email.tld": "doe"
     }
  }
];

const searchingEmail = "john@email.tld";

const filtered = collection.filter(obj => Object.keys(obj.emailsandnames).includes(searchingEmail))

console.log(filtered)

我试着用这个过滤器来实现它:
{emailsandnames["john@email.tld"]: {$exist: true}}
"{emailsandnames['john@email.tld']": {$exist: true}}
但是他们没有成功

66bbxpm5

66bbxpm51#

在字段名中存储数据通常被认为是一种反模式。
可以使用聚合查询现有模式,方法是首先将{email:name}对象添加到数组中。但是,此方法无法很好地扩展,因为它无法使用索引,并且需要对每个查询进行集合扫描。
管道将类似于:

  • 将emailsandnames对象转换为数组,存储在新字段中
  • 筛选新字段以找到所需的匹配项
  • 删除新字段
[
 {$addFields: {emailnamearray: {$objectToArray: "$emailsandnames"}}},
 {$match: {
      "emailnamearray.k": "john@email.tld"
 }},
 {$project: {emailnamearray: 0}}
]

Playground
如果将模式修改为存储具有静态字段名称的对象数组,则查询效率会高得多,例如:

[
  {
    "emailsandnames":  [
       {  
          "email": "john@email.tld",
          "name": "john"
       }
    ]
  }, 
  {
    "emailsandnames": [
       {
         "email":"doe@email.tld",
         "name": "doe"
       }
    ]
  }
]

这将允许使用点表示法查询电子邮件字段,如{"emailsandnames.email": "john@email.tld"},它可以由索引支持,并且可以更好地扩展:

相关问题