如何更新mongodb中的字段? [英] How do i update a field in mongodb?

查看:423
本文介绍了如何更新mongodb中的字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是更新itemSchema中每个对象的timeleft字段.

const ItemSchema = mongoose.Schema({
    name: String,
    time: { type: Date, default: Date.now },
    timeleft: { type: Number, default: 24 }
});

例如,为了让我更新ItemSchema

中的每个对象

ItemSchema.methods.calculateTime = function() { // Done check it one hour

  var currentTime = moment() // Get current Time
  var timeStored = moment.utc(this.time).local().format(); // Convert this.time UTC to local time
  var timeDiff = currentTime.diff(timeStored, 'h'); // See the difference in time example - 7
  this.timeleft -= timeDiff; // Deduct timeleft witht he timeDiff , result would be 17
  this.save(); // Simple save it to the database
}

API示例

app.get('/allItems', function(req, res) {
    Item.find({}, function(err, items) {
      // I want to run items.calculateTime(); but it is not possible.
      // How would I run calculateTime function on the array of objects?
    });
});

我的目标是继续检查时差并将其保存到剩余时间

数据示例

timeleft: 24

// after calculateTime
time: 17 

Because I want to show this to the User

// 17 hours left

该如何处理对象数组而不是单个对象?

解决方案

看看您的用例,我建议您修改解决该问题的方法.显然,您正在创建带有到期日期"的项目(或类似的内容,在下文中,我将使用术语已到期").有效期为创建商品的24小时.

我不会将的值保存到数据库,而是在查询时动态地重新计算. (1)冗余,因为可以根据当前时间和time值来计算,据我了解的问题,(2)您必须连续更新timeleft属性,这似乎很麻烦.

您可以使用Mongoose的参考.

更改架构以确保在创建对象时返回了虚拟物:

const ItemSchema = mongoose.Schema({
  name: String,
  time: { type: Date, default: Date.now }
}, {
  // enable, to have the property available, 
  // when invoking toObject or toJSON
  toJSON: {
    virtuals: true
  },
  toObject: {
    virtuals: true
  }
});

定义虚拟属性timeLeft(我将代码更改为不使用moment即可工作):

// the virtual property, which is not stored in the DB,
// but calculated after querying the database
ItemSchema.virtual('timeLeft').get(function() {
  var millisecondsDifference = Date.now() - this.time.getTime();
  var hoursDifference = millisecondsDifference / (1000 * 60 * 60);
  return Math.max(0, 24 - hoursDifference); // cap to 24 hours
});

您无法查询虚拟属性,因为它们显然不存在于数据库中.相反,当您要查询已过期的商品时,可以搜索在过去24小时内创建的商品.为了方便地执行该操作并将该代码放在一个中央位置,您可以将静态方法附加到您的模式,可以使用ItemModel.findNonExpired:

进行调用

// put the logic for querying non-expired items into
// its own static function, which makes it easier to
// reuse this functionality and understand what's going on
ItemSchema.statics.findNonExpired = function(callback) {
  return this.find({
    time: {
      // find items which have a time within 
      // the last 24 hours
      $gt: new Date(Date.now() - 1000 * 60 * 60 * 24)
    }
  }, callback);
};
const ItemModel = mongoose.model('Item', ItemSchema);

演示:

// create and save some some test items
const items = [
  { name: 'created now' },
  { name: 'created an hour ago', time: new Date(Date.now() - 1000 * 60 * 60) },
  { name: 'created yesterday', time: new Date(Date.now() - 1000 * 60 * 60 * 24) },
  { name: 'created two days ago', time: new Date(Date.now() - 1000 * 60 * 60 * 24 * 2) },
];
ItemModel.create(items, function(err) {
  if (err) throw err;

  ItemModel.findNonExpired(function(err, items) {
    if (err) throw err;
    console.log(items);
  });
});

[edit]现在,这是完整的演练,您应该可以在不进行较大更改的情况下复制和粘贴.

My goal is to update timeleft field on every object in the itemSchema.

const ItemSchema = mongoose.Schema({
    name: String,
    time: { type: Date, default: Date.now },
    timeleft: { type: Number, default: 24 }
});

For example in order for me to update every object in the ItemSchema

ItemSchema.methods.calculateTime = function() { // Done check it one hour

  var currentTime = moment() // Get current Time
  var timeStored = moment.utc(this.time).local().format(); // Convert this.time UTC to local time
  var timeDiff = currentTime.diff(timeStored, 'h'); // See the difference in time example - 7
  this.timeleft -= timeDiff; // Deduct timeleft witht he timeDiff , result would be 17
  this.save(); // Simple save it to the database
}

API example

app.get('/allItems', function(req, res) {
    Item.find({}, function(err, items) {
      // I want to run items.calculateTime(); but it is not possible.
      // How would I run calculateTime function on the array of objects?
    });
});

My goal is to keep checking the time difference and save it to the time left

Data example

timeleft: 24

// after calculateTime
time: 17 

Because I want to show this to the User

// 17 hours left

How would I do this to array of objects, instead of single object?

解决方案

Looking at your use case I would suggest to modify your approach to the problem. Obviously you're creating items with an "expiry date" (or something similar, I'll be using the term "expired" in the following). The expiry is 24 hours from the time where the item was created.

I would not save the value for timeLeft to the DB, but rather recalculate it dynamically upon querying. (1) It's redundant, as it can be calculated from the current time and the time value, as far as I understood your question, (2) you would have to update the timeleft property continuously which seems awkward.

You can make use of Mongoose's virtuals.

Changes to the Schema to make sure, that the virtuals are returned when creating objects:

const ItemSchema = mongoose.Schema({
  name: String,
  time: { type: Date, default: Date.now }
}, {
  // enable, to have the property available, 
  // when invoking toObject or toJSON
  toJSON: {
    virtuals: true
  },
  toObject: {
    virtuals: true
  }
});

Define the virtual property timeLeft (I changed the code to work without moment):

// the virtual property, which is not stored in the DB,
// but calculated after querying the database
ItemSchema.virtual('timeLeft').get(function() {
  var millisecondsDifference = Date.now() - this.time.getTime();
  var hoursDifference = millisecondsDifference / (1000 * 60 * 60);
  return Math.max(0, 24 - hoursDifference); // cap to 24 hours
});

You cannot query on virtual properties, because they obviously do not exist in the database. Instead, when you want to query for items which have reached their expiry date, you can search for items which have been created within the last 24 hours. In order to do that conveniently and have that code at a central place, you can attach a static method to your schema, which you can call using ItemModel.findNonExpired:

// put the logic for querying non-expired items into
// its own static function, which makes it easier to
// reuse this functionality and understand what's going on
ItemSchema.statics.findNonExpired = function(callback) {
  return this.find({
    time: {
      // find items which have a time within 
      // the last 24 hours
      $gt: new Date(Date.now() - 1000 * 60 * 60 * 24)
    }
  }, callback);
};
const ItemModel = mongoose.model('Item', ItemSchema);

Demo:

// create and save some some test items
const items = [
  { name: 'created now' },
  { name: 'created an hour ago', time: new Date(Date.now() - 1000 * 60 * 60) },
  { name: 'created yesterday', time: new Date(Date.now() - 1000 * 60 * 60 * 24) },
  { name: 'created two days ago', time: new Date(Date.now() - 1000 * 60 * 60 * 24 * 2) },
];
ItemModel.create(items, function(err) {
  if (err) throw err;

  ItemModel.findNonExpired(function(err, items) {
    if (err) throw err;
    console.log(items);
  });
});

[edit] This is now a full walkthrough, which you should be able to copy and paste without requiring any big changes.

这篇关于如何更新mongodb中的字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆