Node.js Mongodb 密码特殊字符 @

在去年的 DB 勒索事件之后, 不少的同学开始加强 Mongodb 的安全性, 其中一种办法就是设置复杂的密码. 那么问题来了, 如果设置的密码里包含一些如 “@”, “:” 一样的特殊字符怎么办?

mongodb://username:password@host:port/db

这种情况可能使得你的 Mongodb 连接串不能被正常解析, 并且完全有可能出现. 烦人的地方在于:

  1. 使用 “” 双引号将 password 包起来没有用
  2. 使用 \@ 转义也没有用

解决方案 1

开启 uri_decode_auth 功能, 拼接连接串之后先 encode 一下, 然后通过 uri_decode_auth 在 driver 内部 decode 来绕过这个问题

mongoClient.connect("mongodb://username:p%40ssword@host:port/dbname", {
    uri_decode_auth: true
    }, function(err, db) {

    }
);

解决方案2

老老实实查文档, 在 options 中指明:

mongoose.connect('mongodb://localhost/test',
                 {user: 'username', pass: 'p@ssword'},
                 callback);

MongoDB EmbeddedDocument 与 JSON 转换

今天倒是碰到个很奇怪的问题, schema 中的字段是一个 json 对象包含三个数组, 然后每个数组里面存储 json 对象, 结果取出来数组 arr[i] 里面 json 对象的值 arr[i].key 不出来, 用中括号 arr[i][key] 也取不出来值感觉有些莫名其妙. 随后用 arr[i].constructor 字段查看了一下结果发现这个取出来的数据类型不是常见的 json 那样的 object 而是:

function EmbeddedDocument() {
    Subdocument.apply(this, arguments);
}

关于 EmbeddedDocument 类型, 仔细 google 了一下发现还是一个挺常见的类型确实算是我孤陋寡闻吧. 尝试用 JSON.parse 来转换失败之后研究了一下发现这个 Document 类型有自带很多方法的. 解决方案也很多 :

// 方法1
var json = arr[i].toJson();

// 方法2
arr[i].getValue(key);

// 方法3
arr[i].get(key);

EmbeddedDocument 的内置属性方法

见名之意, 所以直接列举了

  • __parent
  • __parentArray
  • _doc
  • _events
  • _id
  • _lazySetupHooks
  • _maxListeners
  • _posts
  • _pres
  • addListener
  • emit
  • equals
  • errors
  • get
  • getValue
  • hook
  • init
  • inspect
  • invalidate
  • isDirectModified
  • isInit
  • isModified
  • isNew
  • isSelected
  • listeners
  • markModified
  • modifiedPaths
  • on
  • once
  • ownerDocument
  • parent
  • parentArray
  • populate
  • populated
  • post
  • pre
  • remove
  • removeAllListeners
  • removeListener
  • removePre
  • save
  • schema
  • set
  • setMaxListeners
  • setValue
  • toJSON
  • toObject
  • toString
  • type
  • update
  • validate

mongoose 混合类型数据无法写入的BUG

混合类型是指: 当你在 schema 中没有指定字段的类型, 而是使用如 “{}” 之类的类型定义又或者是通过 Schema.Types.Mixed 指定时, 如下两种情况是相等的:

var Any = new Schema({ any: {} });
var Any = new Schema({ any: Schema.Types.Mixed });

如果你使用这种未指定 schema 类型的字段 (schema-less type), 你可以按照你的想法存储任意类型的数据, 但是 Mongoose 也会失去自动检测更改然后 save 更改的能力 (mongoose 为了保证写入的效率, 会做修改检测, 未检测到修改的话就不会写入数据库). 如果要让 Mongoose 去 save 这种混合类型, 你需要主动告诉 Mongoose 该字段有更改, 即调用 document 的 .markModified(path) 方法来做标记, 这样 Mongoose 才知道这个混合字段有更改, 然后才会 save 写入库.

person.anything = { x: [3, 4, { y: "改变" }] };
person.markModified('anything');
person.save(); // anything 字段将会被写入库

官方文档:http://mongoosejs.com/docs/schematypes.html#mixed