微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

javascript – 查询和过滤密钥名称而不是MongoDB中的值

我想从集合中找到部分匹配某个字符串的所有键名.

我得到的最接近的是检查某个密钥是否存在,但这是一个完全匹配:

db.collection.find({ "fkClientID": { $exists:1 }})

我想得到所有以fk开头的键.

解决方法:

如果您有最新的MongoDB 3.4.4,那么您可以在聚合语句中使用$objectToArray,其中$redact作为最快速的方式,可以使用本机运算符.不是扫描集合是“快”.但是你得到的速度最快:

db[collname].aggregate([
  { "$redact": {
    "$cond": {
      "if": {
        "$gt": [
          { "$size": { "$filter": {
            "input": { "$objectToArray": "$$ROOT" },
            "as": "doc",
            "cond": {
              "$eq": [ { "$substr": [ "$$doc.k", 0, 2 ] }, "fk" ]
            }
          }}},
          0
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
 ])

当前未记录的$objectToArray将“对象”转换为数组中的“键”和“值”形式.所以这:

{ "a": 1, "b": 2 }

变成这样:

[{ "k": "a", "v": 1 }, { "k": "b", "v": 2 }]

与$$ROOT一起使用,这是一个引用当前文档“对象”的特殊变量,我们转换为数组,因此可以检查“k”的值.

然后,只需应用$filter并使用$substr来获取“key”字符串的前面字符.

为了记录,这将是MongoDB 3.4.4获得匹配键的唯一列表的最佳方式:

db[collname].aggregate([
  { "$redact": {
    "$cond": {
      "if": {
        "$gt": [
          { "$size": { "$filter": {
            "input": { "$objectToArray": "$$ROOT" },
            "as": "doc",
            "cond": {
              "$eq": [ { "$substr": [ "$$doc.k", 0, 2 ] }, "fk" ]
            }
          }}},
          0
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }},
  { "$project": { 
    "j": {
      "$filter": {
        "input": { "$objectToArray": "$$ROOT" },
         "as": "doc",
         "cond": {
           "$eq": [ { "$substr": [ "$$doc.k", 0, 2 ] }, "fk" ]
         }
      }
    }
  }},
  { "$unwind": "$j" },
  { "$group": { "_id": "$j.k" }}
 ])

这是安全规定,它考虑到密钥可能不存在于所有文档中,并且文档中可能存在多个密钥.

如果你完全确定你“总是”拥有文档中的密钥并且只有一个密钥,那么你可以缩短到只有$group:

db[colname].aggregate([
  { "$group": { 
    "_id": {
      "$arrayElemAt": [
        { "$map": {
          "input": { "$filter": {
            "input": { "$objectToArray": "$$ROOT" },
             "as": "doc",
             "cond": {
               "$eq": [ { "$substr": [ "$$doc.k", 0, 2 ] }, "fk" ]
             }
          }},
          "as": "el",
          "in": "$$el.k"
        }},
        0
      ]
    }
  }}
 ])

早期版本中最有效的方法是使用允许JavaScript表达式进行评估的$where语法.并不是说评估JavaScript的任何东西都是你能做的“最有效”的事情,但分析“密钥”而不是“数据”并不是任何数据存储的最佳选择:

db[collname].find(function() { return Object.keys(this).some( k => /^fk/.test(k) ) })

内联函数只有shell简写,这也可以写成:

db[collname].find({ "$where": "return Object.keys(this).some( k => /^fk/.test(k) )" })

$where的唯一要求是表达式为您要返回的任何文档返回true值,因此文档将保持不变.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐