简体   繁体   English

MongoDB 使用正则表达式过滤动态键和值的文档

[英]MongoDB filter docs on dynamic key and value using regex

Suppose I have multiple fields in a document whose key value I don't know(only the user who has added the keys know that)假设我在一个文档中有多个字段我不知道其键值(只有添加了键的用户才知道)

Now suppose user wants to finds a document specifying the key value, but he forgot what his key value was EXACTLY现在假设用户想要找到一个指定键值的文档,但他忘记了他的键值是什么

So say I have this document:所以说我有这个文件:

name: "John Doe"
class: 5
MisChief: "Bullying"

where the MisChief key was custom created. MisChief 键是自定义创建的。

Suppose user wants to search for 'mischief: bullying'假设用户想要搜索“恶作剧:欺凌”

I can use $regex operator to search for the value, but how can I specify the key as a regex expression ?我可以使用$regex运算符来搜索值,但是如何将键指定为正则表达式

Another way to do this is to return all documents, and doing a case insensitive search for the keys from all those documents which is very inefficient.另一种方法是返回所有文档,并对所有这些文档中的键进行不区分大小写的搜索,这是非常低效的。

So with unknown/dynamic/random key names, one way to do it using aggregation operator $objectToArray :因此,对于未知/动态/随机键名,一种使用聚合运算符$objectToArray的方法:

db.collection.aggregate([
  /** Add a new array field to all docs which contains each field as {k:...,v:...} */
  {
    $addFields: { data: { $objectToArray: "$$ROOT" } }
  },
  /** Match docs that has an object in `data` array which matches with input */
  {
    $match: { "data": { "$elemMatch": { "k": "MisChief", "v": "Bullying" } } } // can be a regex /MisChief/i
  },
  /** Remove added array field from output */
  {
    $project: { "data": 0 }
  }
])

Test: mongoplayground测试: mongoplayground

Ref:aggregation参考:聚合

From your statement:从你的陈述中:

but he forgot what his key value was EXACTLY

If he vaguely remembers Key name/value but doesn't remember it completely - You can do it using regex as you wanted !如果他模糊地记得键名/值但不完全记得 - 您可以根据需要使用正则表达式! But if he forgets it entirely then you can't do much just get all docs where data.v: 'Bullying' & use $match stage to filter further on name of user.但是,如果他完全忘记了,那么您将无能为力,只需获取data.v: 'Bullying'所有文档并使用$match阶段进一步过滤用户name

db.collection.aggregate([
  {
    $addFields: { data: { $objectToArray: "$$ROOT" } }
  },
  {
    $match: { "data": { "$elemMatch": { "v": "Bullying" } } } 
  },
  {
    $project: { "data": 0 }
  }
])

Test: mongoplayground测试: mongoplayground

Note:笔记:

For one single element { "v": "Bullying" } we don't need to use $elemMatch but to keep syntax consistent we're using it, otherwise you can just use data.v: 'Bullying' in $match stage.对于单个元素{ "v": "Bullying" } ,我们不需要使用$elemMatch ,但为了保持语法一致,我们正在使用它,否则您可以在$match阶段使用data.v: 'Bullying'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM