【问题标题】:Check if a MongoDB value exists before inserting在插入之前检查 MongoDB 值是否存在
【发布时间】:2019-02-09 21:09:05
【问题描述】:

我正在制作一个带有 Twilio 的 MEAN 应用程序,它允许人们通过向应用程序发送他们的姓名来签署在线请愿书。人们应该只能在请愿书上签名一次。我计划通过每个电话号码只允许一个签名来确保这一点。

每次签署请愿书时,都会创建一个这样的 Mongo 对象:

{ 
  "_id" : ObjectId("5c5a47ae8f04f9148f43b033"),          
  "name" : "John Doe", 
  "number" : "+18373987466", 
  "date" : "2/5/19" 
}

我已经将number 字段变成了一个唯一索引,所以每个电话号码只能有一个签名。

我遇到的问题是当有人试图多次签署请愿书时该怎么办。我想拦截他们的尝试并向他们发送一条消息,说他们已经签署了请愿书。

在我看来,我有两个选择:

选项 #1 查询数据库,看看是否已经输入了相同的数字。

这看起来应该很容易,但我就是不知道该怎么做。

var number = '+18373987466';
if(collection.find({"number":number}) {
  twiml.message("You have already signed the petition");
}

我的想法是collection.find({"number":number}) 如果找到具有相同编号的条目,将返回true。但是,它会返回整个 Mongo 游标。

选项 #2 由于number 是唯一索引,因此如果使用相同值创建另一个对象,Mongo 将抛出错误。我可以拦截抛出的错误,然后向用户发送消息。

我对这种方法的第一个问题是:故意让您的应用抛出错误是一种好的软件设计吗?

我使用try/catch 块尝试了这种方法,但引发的错误立即使应用程序崩溃。

try {
  collection.insertOne(
    {name : name, number : number, date: dateSigned}, 
    function(error, result) {
      console.log(`${name} has been added to the database`);
  });
} catch (error) {
  // handle error
}

这不是“捕获”错误并防止应用程序崩溃的正确方法吗?

【问题讨论】:

  • 你试过使用猫鼬吗?当我使用 node.js 和 mongodb 时,这通常是我的选择。因为它提供了 Schemas,所以一个独特的字段非常简单。 mongoosejs.com/docs/schematypes.html 这应该稍微澄清一下。文档其实还不错
  • 我对这个应用程序的数据库需求非常简单,以至于 Mongoose 看起来有点矫枉过正。

标签: javascript node.js mongodb express twilio


【解决方案1】:

选项#1

描述的行为是正确的,如果你使用collection.find(),MongoDB 将返回一个游标。你可以使用collection.count()。但由于您只对已经存在至少一个值感兴趣,因此您可以致电cursor.limit(1)

if (collection.find({"number":number}).limit(1).length === 1) 
   twiml.message("You have already signed the petition");

选项 #2

故意让你的应用程序抛出一个好的软件设计吗? 错误?

没有。我认为这是一个糟糕的设计。如果该条目已经存在,我不会将其视为错误,而是需要特殊处理的情况。如果您使用catch(),您仍然需要检查向用户发送正确消息的错误类型。
想象一下您的数据库无法访问,因此您无法插入新值,这将是一个(真正的)错误,您应该 catch() 它。

【讨论】:

  • 条件语句不起作用,因为 .limit(1) 返回的是 Mongo 游标,而不是数字。不过,您的建议确实使我朝着正确的方向前进。我刚刚切换了 count() 和 limit(),因为 count() 返回一个数字并提供回调。
  • 你是对的,你可以简单地使用 db.collection.find().limit(1)。编辑了我的答案。
【解决方案2】:
var number = '+18373987466';
result = collection.find_one({"number":number}) 
if result is not None:
    twiml.message("You have already signed the petition");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-12
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多