【问题标题】:How to shorten MongoDB ObjectId and use it in Mongoose schema如何缩短 MongoDB ObjectId 并在 Mongoose 模式中使用它
【发布时间】:2016-09-14 01:20:46
【问题描述】:

我正在寻找一种方法来缩短 MongoDB 数据库生成的 ObjectID,并且我知道一些现有的库,例如 'shortid''short-mongo-id'

但是,我的问题是我希望在 mongoose 架构中为集合中存在的每个文档创建一个新的“shortID”字段,并且这个新字段应该是唯一的,并且理想情况下是附加到文档。 像这样:

var subjectSchema = new Schema({

    shortID: {required: true, unique: true}, 
    //must be unique to each document and is same everytime server restarts

    Sex: {type: String, enum: enumSex},
    Diagnosis: String,
    Projects:[projectPerSubjectSchema]
});   

“shortid”https://www.npmjs.com/package/shortid 库运行良好,并且确实生成了唯一的 id,但是每次服务器重新启动时它都会生成不同的 id,这不是我想要的。

我尝试的另一个库 'short-mongo-id' https://www.npmjs.com/package/short-mongo-id 能够将 ObjectId 转换为唯一 ID 字符串的截断版本,但是,我不确定如何在创建模式时使用它。我试过了:

ID: {type: String, 'default': shortid((this.ObjectId).valueOf()), unique: true}

尝试使用 this.ObjectId 获取文档的 ObjectId,使用 valueOf() 对其进行字符串化,但终端显示:

TypeError: Cannot read property 'valueOf' of undefined 

所有代码都是在 Node.JS 中完成的,我对 NodeJS 和 MongoDB 都很陌生,所以如果我在上面提供的代码中犯了一些重大错误,请纠正我。提前致谢!

【问题讨论】:

  • 你需要实现一个custom type。但是退后一步:为什么不能使用常规的ObjectId's?
  • 我认为这会使查询特定对象的信息变得困难,因为用户需要输入长 ID,而且 URL 看起来非常混乱。我可能是错的,如果有更好的方法可以轻松地基于 ObjectId 进行查询,请告诉我
  • 也许有一种方法可以完全不用 id 来打扰用户?即使它们很短,任何形式的 id 通常都不适合普通人处理。
  • 如果 Id 很短,您可能很快就会遇到重复 Id 的问题......另一方面,有一些众所周知的方法可以避免使用 Id 进行查询......跨度>

标签: javascript node.js mongodb mongoose objectid


【解决方案1】:

shortid 模块应该可以满足您的需要,您只需将 shortId 保存为普通 String 字段,并确保在保存之前生成新代码,如下所示(在 mongoose 模式定义中):

const mongoose = require('mongoose')
const shortid = require('shortid')
const Schema = mongoose.Schema
const schema = new Schema({
  _shortId: {
    type: String,
    unique: true
  },
  ... // other fields...
})
// This is for checking if the document already have a _shortId, 
// so you don't replace it with a new code
schema.pre('save', function (next) {
  let doc = this

  if (!this._shortId) { 
    addShortId(doc, next)
  } 
})

function addShortId (doc, next) {
  let newShortId = shortid.generate()
  doc.constructor.findOne({_shortId: newShortId}).then((docRes) => {
    if (docRes) {
      addShortId(doc, next)
    } else {
      doc._shortId = newCode
      next()
    }
  }, (err) => {
    next(err)
  })
}

如果你想为所有现有文档插入一个_showId,你只需要一个forEach并再次保存模型,这就是我正在做的(使用https://github.com/JMPerez/promise-throttle,因为它是一个巨大的集合,调用save () 一下子会减慢服务器的速度):

XXXXX.find({ '_shortId': { '$exists': false } }).then((data) => {
  var promiseThrottle = new PromiseThrottle({
    requestsPerSecond: 50,
    promiseImplementation: Promise
  })
  var i = 1
  data.forEach(element => {
  var myFunction = function (j) {
    return element.save()
  }
  promiseThrottle.add(myFunction.bind(this, i++)).then(ss => {
    console.log('done ' + ss._shortId)
  })
})

部分代码改编自:https://github.com/dylang/shortid/issues/65

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 2015-03-13
    • 1970-01-01
    • 2012-10-27
    • 2016-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多