六、API

1、new Datastore(options)

作用:

初始化一个数据存储,相当于 MongoDB 的一个集合、Mysql 的一张表。

options 对象配置参数:

① filename(可选): 数据存储文件路径。如果为空,数据将会自动存储在内存中。注意路径不能以“~” 结尾。

② inMemoryOnly(可选, 默认 false): 数据存储方式。是否只存在于内存中。

③ loadDatabase: 将数据加载到内存中。

④ timestampData(可选, 默认 false): 自动生成时间戳,字段为 createdAt 和 updateAt,用来记录文档插入和更新操作的时间点。

⑤ autoload(可选, 默认 false): 如果使用 autoload,当数据存储被创建时,数据将自动从文件中加载到内存,不必去调用 loadDatabase。注意所有命令操作只有在数据加载完成后才会被执行。

⑥ onload(可选): 在数据加载完成后被调用,也就是在 loadDatabase 方法调用后触发。该方法有一个 error 参数,如果试用了 autoload,而且没有定义该方法,在数据加载过程中出错将默认会抛出该错误。

⑦ afterSerialization(可选): 在数据被序列化成字符串之后和被写入磁盘前,可以使用该方法对数据进行转换。比如可以做一些数据加密工作。该方法入参为一个字符串 (绝对不能含有字符“\n”,否则数据会丢失),返回转换后的字符串。

⑧ beforeDeserialization(可选): 与 afterSerialization 相反。两个必须成对出现,否则会引起数据丢失,可以理解为一个加密解密的过程。

⑨ corruptAlertThreshold(可选): 默认 10%, 取值在 0-1 之间。如果数据文件损坏率超过这个百分比,NeDB 将不会启动。取 0,意味着不能容忍任何数据损坏;取 1,意味着忽略数据损坏问题。

⑩ compareStrings(可选): compareStrings(a, b) 比较两个字符串,返回-1、0 或者 1。如果被定义,将会覆盖默认的字符串比较方法,用来兼容默认方法不能比较非 US 字符的缺点。

注:如果使用本地存储,而且没有配置 autoload 参数,需要手动调用 loadDatabase 方法,所有操作 (insert, find, update, remove) 在该方法被调用前都不会执行。还有就是,如果 loadDatabase 失败,所有命令也将不会执行。

示例

  1. // 示例 1: 内存数据库(没有必要调用loadDatabase方法)
  2. varDatastore=require('nedb'),
  3. db=newDatastore();
  4. // 示例 2: 本地存储需要手动调用loadDatabase方法
  5. varDatastore=require('nedb'),
  6. db=newDatastore({filename:'path/to/datafile'});
  7. db.loadDatabase(function(err){ // 回调函数(可选)
  8. // Now commands will be executed
  9. });
  10. // 示例 3: 带有autoload配置项的本地存储
  11. varDatastore=require('nedb'),
  12. db=newDatastore({filename:'path/to/datafile',autoload:true});
  13. // You can issue commands right away
  14. // 示例 4: 创建多个数据存储
  15. db={};
  16. db.users=newDatastore('path/to/users.db');
  17. db.robots=newDatastore('path/to/robots.db');
  18. // 如果不配置autoload,需要加载数据库(该方法是异步的)
  19. db.users.loadDatabase();
  20. db.robots.loadDatabase();

2、db.insert(doc, callback)

作用:

插入文档数据 (文档相当于 mysql 表中的一条记录)。如果文档不包含_id 字段,NeDB 会自动生成一个,该字段是 16 个字符长度的数字字符串。该字段一旦确定,就不能被更改。

参数:

doc: 支持 String, Number, Boolean, Date, null, array 以及 object 类型。如果该字段是 undefined 类型,将不会被保存,这里和 MongoDB 处理方式有点不同,MongoDB 会将 undefined 转换为 null 进行存储。字段名称不能以”$” 开始,也不能包含”.”。

callback(可选): 回调函数,包含参数 err 以及 newDoc,err 是报错,newDoc 是新插入的文档,包含它的_id 字段。

示例

  1. vardoc={hello:'world'
  2. ,n:5
  3. ,today:newDate()
  4. ,nedbIsAwesome:true
  5. ,notthere:null
  6. ,notToBeSaved:undefined // 该字段不会被保存
  7. ,fruits:['apple','orange','pear']
  8. ,infos:{name:'nedb'}
  9. };
  10. db.insert(doc,function(err,newDoc){ // Callback is optional
  11. // newDoc is the newly inserted document, including its _id
  12. // newDoc has no key called notToBeSaved since its value was undefined
  13. });
  14. // 使用array,实现批量插入。一旦其中一个操作失败,所有改变将会回滚。
  15. db.insert([{a:5},{a:42}],function(err,newDocs){
  16. // Two documents were inserted in the database
  17. // newDocs is an array with these documents, augmented with their _id
  18. });
  19. // 如果a字段有唯一性约束,该操作将会执行失败。
  20. db.insert([{a:5},{a:42},{a:5}],function(err){
  21. // err is a 'uniqueViolated' error
  22. // The database was not modified
  23. });

3、db.find(query, callback)

作用:

查询符合条件的文档集。

参数:

query: object 类型,查询条件。支持使用比较运算符 ($lt, $lte, $gt, $gte, $in, $nin, $ne), 逻辑运算符 ($or, $and, $not, $where), 正则表达式进行查询。

callback(可选): 回调函数,包含参数 err 以及 docs,err 是报错,docs 是查询到的文档集。

示例:

  1. // 数据存储集合
  2. // { _id: 'id1', planet: 'Mars', system: 'solar', inhabited: false, satellites: ['Phobos', 'Deimos'] }
  3. // { _id: 'id2', planet: 'Earth', system: 'solar', inhabited: true, humans: { genders: 2, eyes: true } }
  4. // { _id: 'id3', planet: 'Jupiter', system: 'solar', inhabited: false }
  5. // { _id: 'id4', planet: 'Omicron Persei 8', system: 'futurama', inhabited: true, humans: { genders: 7 } }
  6. // { _id: 'id5', completeData: { planets: [ { name: 'Earth', number: 3 }, { name: 'Mars', number: 2 }, { name: 'Pluton', number: 9 } ] } }
  7. // 示例1: 基本查询。可以使用正则表达式匹配字符串。使用“.”匹配对象或者数组里面的元素。
  8. // 单字段查询
  9. db.find({system:'solar'},function(err,docs){
  10. // docs is an array containing documents Mars, Earth, Jupiter
  11. // If no document is found, docs is equal to []
  12. });
  13. // 正则表达式查询
  14. db.find({planet:/ar/},function(err,docs){
  15. // docs contains Mars and Earth
  16. });
  17. // 多条件查询
  18. db.find({system:'solar',inhabited:true},function(err,docs){
  19. // docs is an array containing document Earth only
  20. });
  21. // 根据对象属性查询
  22. db.find({"humans.genders":2},function(err,docs){
  23. // docs contains Earth
  24. });
  25. // 根据数组对象属性查询
  26. db.find({"completeData.planets.name":"Mars"},function(err,docs){
  27. // docs contains document 5
  28. });
  29. db.find({"completeData.planets.name":"Jupiter"},function(err,docs){
  30. // docs is empty
  31. });
  32. db.find({"completeData.planets.0.name":"Earth"},function(err,docs){
  33. // docs contains document 5
  34. // If we had tested against "Mars" docs would be empty because we are matching against a specific array element
  35. });
  36. // 对象深度比较查询,不要与"."使用混淆
  37. db.find({humans:{genders:2}},function(err,docs){
  38. // docs is empty, because { genders: 2 } is not equal to { genders: 2, eyes: true }
  39. });
  40. // 查询所有结果集
  41. db.find({},function(err,docs){
  42. });
  43. // 查询某一个文档
  44. db.findOne({_id:'id1'},function(err,doc){
  45. // doc is the document Mars
  46. // If no document is found, doc is null
  47. });
  48. // 示例2: {field: {$op: value}} ($op代表任意比较运算符)
  49. // $lt, $lte: 小于,小于等于
  50. // $gt, $gte: 大于,大于等于
  51. // $in: 属于
  52. // $ne, $nin: 不等于,不属于
  53. // $exists: 取值为true或者false,用于检测文档是否具有某一字段
  54. // $regex: 检测字符串是否与正则表达式相匹配
  55. // $lt, $lte, $gt and $gte 只能用于数字和字符串类型
  56. db.find({"humans.genders":{$gt:5}},function(err,docs){
  57. // docs contains Omicron Persei 8, whose humans have more than 5 genders (7).
  58. });
  59. // 当进行字符串比较的时候,将使用字典序。
  60. db.find({planet:{$gt:'Mercury'}},function(err,docs){
  61. // docs contains Omicron Persei 8
  62. })
  63. // Using $in. $nin is used in the same way
  64. db.find({planet:{$in:['Earth','Jupiter']}},function(err,docs){
  65. // docs contains Earth and Jupiter
  66. });
  67. // Using $exists
  68. db.find({satellites:{$exists:true}},function(err,docs){
  69. // docs contains only Mars
  70. });
  71. // Using $regex with another operator
  72. db.find({planet:{$regex:/ar/,$nin:['Jupiter','Earth']}},function(err,docs){
  73. // docs only contains Mars because Earth was excluded from the match by $nin
  74. });
  75. // 示例3: 当文档中有一个字段是数组,NeDB将首先判断查询值是否为数组,如果是数组的话将执行精确查找,然后再去判断是否存在数组比较方法(现在只支持$size和$elemMatch)。如果都没有,将会对所有元素进行查询。
  76. // $size: 匹配数组的大小
  77. // $elemMatch: 匹配至少一个数组元素
  78. // 精确查找
  79. db.find({satellites:['Phobos','Deimos']},function(err,docs){
  80. // docs contains Mars
  81. })
  82. db.find({satellites:['Deimos','Phobos']},function(err,docs){
  83. // docs is empty
  84. })
  85. // 使用数组比较方法
  86. // $elemMatch 运算符将匹配数组中满足所有条件的元素
  87. db.find({completeData:{planets:{$elemMatch:{name:'Earth',number:3}}}},function(err,docs){
  88. // docs contains documents with id 5 (completeData)
  89. });
  90. db.find({completeData:{planets:{$elemMatch:{name:'Earth',number:5}}}},function(err,docs){
  91. // docs is empty
  92. });
  93. // 在$elemMatch中使用比较运算符
  94. db.find({completeData:{planets:{$elemMatch:{name:'Earth',number:{$gt:2}}}}},function(err,docs){
  95. // docs contains documents with id 5 (completeData)
  96. });
  97. // 注意不能使用嵌套的运算符, e.g. { $size: { $lt: 5 } } 将会抛出异常
  98. db.find({satellites:{$size:2}},function(err,docs){
  99. // docs contains Mars
  100. });
  101. db.find({satellites:{$size:1}},function(err,docs){
  102. // docs is empty
  103. });
  104. // If a document's field is an array, matching it means matching any element of the array
  105. db.find({satellites:'Phobos'},function(err,docs){
  106. // docs contains Mars. Result would have been the same if query had been { satellites: 'Deimos' }
  107. });
  108. // This also works for queries that use comparison operators
  109. db.find({satellites:{$lt:'Amos'}},function(err,docs){
  110. // docs is empty since Phobos and Deimos are after Amos in lexicographical order
  111. });
  112. // This also works with the $in and $nin operator
  113. db.find({satellites:{$in:['Moon','Deimos']}},function(err,docs){
  114. // docs contains Mars (the Earth document is not complete!)
  115. });
  116. // 示例4: 逻辑运算符 $or, $and, $not, $where
  117. // $or, $and: 并集,交集 { $op: [query1, query2, ...] }
  118. // $not: 取非 { $not: query }
  119. // $where: 条件 { $where: function () { /* object is "this", return a boolean */ } }
  120. db.find({$or:[{planet:'Earth'},{planet:'Mars'}]},function(err,docs){
  121. // docs contains Earth and Mars
  122. });
  123. db.find({$not:{planet:'Earth'}},function(err,docs){
  124. // docs contains Mars, Jupiter, Omicron Persei 8
  125. });
  126. db.find({$where:function(){returnObject.keys(this)>6;}},function(err,docs){
  127. // docs with more than 6 properties
  128. });
  129. // You can mix normal queries, comparison queries and logical operators
  130. db.find({$or:[{planet:'Earth'},{planet:'Mars'}],inhabited:true},function(err,docs){
  131. // docs contains Earth
  132. });
  133. // 示例5: Projections
  134. // 在第二个参数传入projections对象,来规定返回字段。比如: {a:1, b:1}指定只返回a和b字段,{a:0, b:0}指定省略a和b这两个字段。
  135. // _id默认返回,不需要返回设置_id: 0
  136. // Same database as above
  137. // Keeping only the given fields
  138. db.find({planet:'Mars'},{planet:1,system:1},function(err,docs){
  139. // docs is [{ planet: 'Mars', system: 'solar', _id: 'id1' }]
  140. });
  141. // Keeping only the given fields but removing _id
  142. db.find({planet:'Mars'},{planet:1,system:1,_id:0},function(err,docs){
  143. // docs is [{ planet: 'Mars', system: 'solar' }]
  144. });
  145. // Omitting only the given fields and removing _id
  146. db.find({planet:'Mars'},{planet:0,system:0,_id:0},function(err,docs){
  147. // docs is [{ inhabited: false, satellites: ['Phobos', 'Deimos'] }]
  148. });
  149. // Failure: using both modes at the same time
  150. db.find({planet:'Mars'},{planet:0,system:1},function(err,docs){
  151. // err is the error message, docs is undefined
  152. });
  153. // You can also use it in a Cursor way but this syntax is not compatible with MongoDB
  154. db.find({planet:'Mars'}).projection({planet:1,system:1}).exec(function(err,docs){
  155. // docs is [{ planet: 'Mars', system: 'solar', _id: 'id1' }]
  156. });
  157. // Project on a nested document
  158. db.findOne({planet:'Earth'}).projection({planet:1,'humans.genders':1}).exec(function(err,doc){
  159. // doc is { planet: 'Earth', _id: 'id2', humans: { genders: 2 } }
  160. });
  161. // 示例6:排序和分页
  162. // 文档集
  163. // doc1 = { _id: 'id1', planet: 'Mars', system: 'solar', inhabited: false, satellites: ['Phobos', 'Deimos'] }
  164. // doc2 = { _id: 'id2', planet: 'Earth', system: 'solar', inhabited: true, humans: { genders: 2, eyes: true } }
  165. // doc3 = { _id: 'id3', planet: 'Jupiter', system: 'solar', inhabited: false }
  166. // doc4 = { _id: 'id4', planet: 'Omicron Persei 8', system: 'futurama', inhabited: true, humans: { genders: 7 } }
  167. // No query used means all results are returned (before the Cursor modifiers)
  168. db.find({}).sort({planet:1}).skip(1).limit(2).exec(function(err,docs){
  169. // docs is [doc3, doc1]
  170. });
  171. // You can sort in reverse order like this
  172. db.find({system:'solar'}).sort({planet:-1}).exec(function(err,docs){
  173. // docs is [doc1, doc3, doc2]
  174. });
  175. // You can sort on one field, then another, and so on like this:
  176. db.find({}).sort({firstField:1,secondField:-1})... // You understand how this works!

4、db.findOne(query, callback)

作用:

查询符合条件的一个文档。与 db.find 使用相同。

5、db.update(query, update, options, callback)

作用:

根据 update 参数的规则,更新匹配到 query 的结果集。

参数:

query: 与 find 和 findOne 中 query 参数的用法一致

update: 指定文档更改规则。该参数可以是一个新的文档,也可以是一套修饰符,两者不能同时使用。使用修饰符时,如果需要更改的字段不存在,将会自动创建。可用的修饰符有 $set(改变字段值), $unset(删除某一字段), $inc(增加某一字段), $min/$max(改变字段值,传入值需要小于/大于当前值), 还有一些用在数组上的修饰符,$push, $pop, $addTopSet, $pull, $each, $slice,具体用法如下示例。

options: object 类型。muti(默认 false),是否允许修改多条文档;upsert(默认为 false),如果 query 没有匹配到结果集,有两种情况需要考虑,一个是 update 是一个简单的对象 (不包含任何修饰符),另一种情况是带有修饰符,对第一种情况会直接将该文档插入,对第二种情况会将通过修饰符更改后的文档插入;

callback(可选): 参数 (err, numAffected, affectedDocuments, upsert)。numAffected:被影响的文档个数;affectedDocuments:更新后的文档。

注意:_id 不能被修改

示例:

  1. // 文档集
  2. // { _id: 'id1', planet: 'Mars', system: 'solar', inhabited: false }
  3. // { _id: 'id2', planet: 'Earth', system: 'solar', inhabited: true }
  4. // { _id: 'id3', planet: 'Jupiter', system: 'solar', inhabited: false }
  5. // { _id: 'id4', planet: 'Omicron Persia 8', system: 'futurama', inhabited: true }
  6. // 用一个文档替换另一个文档
  7. db.update({planet:'Jupiter'},{planet:'Pluton'},{},function(err,numReplaced){
  8. // numReplaced = 1
  9. // The doc #3 has been replaced by { _id: 'id3', planet: 'Pluton' }
  10. // Note that the _id is kept unchanged, and the document has been replaced
  11. // (the 'system' and inhabited fields are not here anymore)
  12. });
  13. // 设定一个已存字段的值
  14. db.update({system:'solar'},{$set:{system:'solar system'}},{multi:true},function(err,numReplaced){
  15. // numReplaced = 3
  16. // Field 'system' on Mars, Earth, Jupiter now has value 'solar system'
  17. });
  18. // 设定一个不存在字段的值
  19. db.update({planet:'Mars'},{$set:{"data.satellites":2,"data.red":true}},{},function(){
  20. // Mars document now is { _id: 'id1', system: 'solar', inhabited: false
  21. // , data: { satellites: 2, red: true }
  22. // }
  23. // Not that to set fields in subdocuments, you HAVE to use dot-notation
  24. // Using object-notation will just replace the top-level field
  25. db.update({planet:'Mars'},{$set:{data:{satellites:3}}},{},function(){
  26. // Mars document now is { _id: 'id1', system: 'solar', inhabited: false
  27. // , data: { satellites: 3 }
  28. // }
  29. // You lost the "data.red" field which is probably not the intended behavior
  30. });
  31. });
  32. // 删除一个字段
  33. db.update({planet:'Mars'},{$unset:{planet:true}},{},function(){
  34. // Now the document for Mars doesn't contain the planet field
  35. // You can unset nested fields with the dot notation of course
  36. });
  37. // 设置upsert
  38. db.update({planet:'Pluton'},{planet:'Pluton',inhabited:false},{upsert:true},function(err,numReplaced,upsert){
  39. // numReplaced = 1, upsert = { _id: 'id5', planet: 'Pluton', inhabited: false }
  40. // A new document { _id: 'id5', planet: 'Pluton', inhabited: false } has been added to the collection
  41. });
  42. // If you upsert with a modifier, the upserted doc is the query modified by the modifier
  43. // This is simpler than it sounds :)
  44. db.update({planet:'Pluton'},{$inc:{distance:38}},{upsert:true},function(){
  45. // A new document { _id: 'id5', planet: 'Pluton', distance: 38 } has been added to the collection
  46. });
  47. // If we insert a new document { _id: 'id6', fruits: ['apple', 'orange', 'pear'] } in the collection,
  48. // let's see how we can modify the array field atomically
  49. // $push inserts new elements at the end of the array
  50. db.update({_id:'id6'},{$push:{fruits:'banana'}},{},function(){
  51. // Now the fruits array is ['apple', 'orange', 'pear', 'banana']
  52. });
  53. // $pop removes an element from the end (if used with 1) or the front (if used with -1) of the array
  54. db.update({_id:'id6'},{$pop:{fruits:1}},{},function(){
  55. // Now the fruits array is ['apple', 'orange']
  56. // With { $pop: { fruits: -1 } }, it would have been ['orange', 'pear']
  57. });
  58. // $addToSet adds an element to an array only if it isn't already in it
  59. // Equality is deep-checked (i.e. $addToSet will not insert an object in an array already containing the same object)
  60. // Note that it doesn't check whether the array contained duplicates before or not
  61. db.update({_id:'id6'},{$addToSet:{fruits:'apple'}},{},function(){
  62. // The fruits array didn't change
  63. // If we had used a fruit not in the array, e.g. 'banana', it would have been added to the array
  64. });
  65. // $pull removes all values matching a value or even any NeDB query from the array
  66. db.update({_id:'id6'},{$pull:{fruits:'apple'}},{},function(){
  67. // Now the fruits array is ['orange', 'pear']
  68. });
  69. db.update({_id:'id6'},{$pull:{fruits:$in:['apple','pear']}},{},function(){
  70. // Now the fruits array is ['orange']
  71. });
  72. // $each can be used to $push or $addToSet multiple values at once
  73. // This example works the same way with $addToSet
  74. db.update({_id:'id6'},{$push:{fruits:{$each:['banana','orange']}}},{},function(){
  75. // Now the fruits array is ['apple', 'orange', 'pear', 'banana', 'orange']
  76. });
  77. // $slice can be used in cunjunction with $push and $each to limit the size of the resulting array.
  78. // A value of 0 will update the array to an empty array. A positive value n will keep only the n first elements
  79. // A negative value -n will keep only the last n elements.
  80. // If $slice is specified but not $each, $each is set to []
  81. db.update({_id:'id6'},{$push:{fruits:{$each:['banana'],$slice:2}}},{},function(){
  82. // Now the fruits array is ['apple', 'orange']
  83. });
  84. // $min/$max to update only if provided value is less/greater than current value
  85. // Let's say the database contains this document
  86. // doc = { _id: 'id', name: 'Name', value: 5 }
  87. db.update({_id:'id1'},{$min:{value:2}},{},function(){
  88. // The document will be updated to { _id: 'id', name: 'Name', value: 2 }
  89. });
  90. db.update({_id:'id1'},{$min:{value:8}},{},function(){
  91. // The document will not be modified
  92. });

6、db.remove(query, options, callback)

作用:

根据 options 配置删除所有 query 匹配到的文档集。

参数:

query: 与 find 和 findOne 中 query 参数的用法一致

options: 只有一个可用。muti(默认 false),允许删除多个文档。

callback: 可选,参数: err, numRemoved

示例:

  1. // 文档集
  2. // { _id: 'id1', planet: 'Mars', system: 'solar', inhabited: false }
  3. // { _id: 'id2', planet: 'Earth', system: 'solar', inhabited: true }
  4. // { _id: 'id3', planet: 'Jupiter', system: 'solar', inhabited: false }
  5. // { _id: 'id4', planet: 'Omicron Persia 8', system: 'futurama', inhabited: true }
  6. // 删除一条记录
  7. // options set to {} since the default for multi is false
  8. db.remove({_id:'id2'},{},function(err,numRemoved){
  9. // numRemoved = 1
  10. });
  11. // 删除多条记录
  12. db.remove({system:'solar'},{multi:true},function(err,numRemoved){
  13. // numRemoved = 3
  14. // All planets from the solar system were removed
  15. });
  16. // 删除所有记录
  17. db.remove({},{multi:true},function(err,numRemoved){
  18. });

7、db.ensureIndex(options, callback)

作用:

NeDB 支持索引。索引可以提高查询速度以及保证字段的唯一性。索引可以用在任何字段,包括嵌套很深的字段。目前,索引只能用来加速基本查询以及使用 $in, $lt, $lte, $gt 和 $gte 运算符的查询,如上 find 接口中示例所示。保证索引不为数组对象。方法可以在任何时候被调用,推荐在应用启动时就调用 (该方法是同步的, 为 1000 个文档添加索引仅需 35ms)。

参数:

fieldName(必须): 索引字段,使用“.” 给嵌套的字段加索引。

unique(可选,默认 false): 字段唯一性约束。注意:唯一性约束会增加为两个文档中没有定义的字段添加索引的错误。

sparse(可选,默认 false): 不能为没有定义的字段加索引。如果接受给多个文档中没有定义的字段添加索引,给需要该配置参数与 unique 一起使用。

expireAfterSeconds(可选,秒数): TTL 索引,设置自动过期时间。

删除索引: db.removeIndex(fieldName, cb)

注意:_id 字段会自动加索引和唯一性约束,不必再为它使用 ensureIndex。如果使用本地存储,索引也将保存在数据文件中,当第二次加载数据库时,索引也将自动被添加。如果加载一个已经有索引的数据库,删除索引将不起任何作用。

  1. db.ensureIndex({fieldName:'somefield'},function(err){
  2. // If there was an error, err is not null
  3. });
  4. // 对索引设置唯一性约束
  5. db.ensureIndex({fieldName:'somefield',unique:true},function(err){
  6. });
  7. // Using a sparse unique index
  8. db.ensureIndex({fieldName:'somefield',unique:true,sparse:true},function(err){
  9. });
  10. // 使用唯一性约束制造错误,查看err的格式
  11. db.insert({somefield:'nedb'},function(err){
  12. // err is null
  13. db.insert({somefield:'nedb'},function(err){
  14. // err is { errorType: 'uniqueViolated'
  15. // , key: 'name'
  16. // , message: 'Unique constraint violated for key name' }
  17. });
  18. });
  19. // 移除somefield字段的索引
  20. db.removeIndex('somefield',function(err){
  21. });
  22. // Example of using expireAfterSeconds to remove documents 1 hour
  23. // after their creation (db's timestampData option is true here)
  24. db.ensureIndex({fieldName:'createdAt',expireAfterSeconds:3600},function(err){
  25. });
  26. // You can also use the option to set an expiration date like so
  27. db.ensureIndex({fieldName:'expirationDate',expireAfterSeconds:0},function(err){
  28. // Now all documents will expire when system time reaches the date in their
  29. // expirationDate field
  30. });

8、db.count(query, callback)

作用:

计数。与 find 用法相同。

示例:

  1. // Count all planets in the solar system
  2. db.count({system:'solar'},function(err,count){
  3. // count equals to 3
  4. });
  5. // Count all documents in the datastore
  6. db.count({},function(err,count){
  7. // count equals to 4
  8. });

9、db.persistence.compactDatafile

作用:

为了性能考虑,NeDB 存储使用 append-only 格式,意味着所有的更改和删除操作其实都是被添加到了文件末尾。每次加载数据库时,数据库会自动被压缩,才能拿到规范的文档集。

也可以手动调用压缩方法 db.persistence.compactDatafile(该方法没有参数)。函数内部有队列机制,保证命令按顺序执行。执行完成后,会触发 compaction.done 事件。

也可以设置自动压缩方法 db.persistence.setAutocompactionInterval(interval) 来定时执行。interval 是毫秒级别 (大于 5000ms)。停止自动压缩使用方法 db.persistence.stopAutocompaction()。

压缩会花费一些时间 (在普通机器上,5w 条记录花费 130ms 处理,并不会耗费太久)。在压缩执行期间,其他操作将不能执行,所以大部分项目不需要使用它。

假设不受 corruptAlertThreshold 参数的限制,压缩将会把损坏的记录全部移除掉。

压缩会强制系统将数据写入磁盘,这就保证了服务崩溃不会引起数据的全部丢失。最坏的情况就是崩溃发生在两个压缩同步操作之间,会导致全部数据的丢失。

性能

在普通机器上,对于 1 万条记录

NeDB 吞吐量 (带索引):

Insert: 5950 ops

Find: 25440 ops

Update: 4490 ops

Remove: 6620 ops