【问题标题】:Pull an entry from an array via Meteor通过 Meteor 从数组中拉出一个条目
【发布时间】:2015-10-29 10:37:09
【问题描述】:

我的 Meteor 1.1.0.2 应用中有以下(简化的)SimpleSchema 架构:

Tickers.attachSchema(
    new SimpleSchema({
        entries: {
            type: [TickerEntries],
            defaultValue: [],
            optional: true
        }
    })
);

TickerEntries = new SimpleSchema({
    id: {
        type: String,
        autoform: {
            type: "hidden",
            label: false,
            readonly: true
        },
        optional: true,
        autoValue: function () {
            if (!this.isSet) {
                return new Mongo.Collection.ObjectID()._str;
            }
        }
    },
    text: {
        type: String,
        label: 'Text'
    }
};

在数据库中,我确实有以下条目:

{
    "_id" : "ZcEvq9viGQ3uQ3QnT",
    "entries" : [
        {
            "text" : "a",
            "id" : "fc29774dadd7b37ee0dc5e3e"
        },
        {
            "text" : "b",
            "id" : "8171c4dbcc71052a8c6a38fb"
        }
    ]
}

我想删除由 ID 指定的条目数组中的一个条目。

如果我在 meteor-mongodb-shell 中执行以下命令,它可以正常工作:

db.Tickers.update({_id:"3TKgHKkGnzgfwqYHY"}, {"$pull":{"entries": {"id":"8171c4dbcc71052a8c6a38fb"}}})

但问题是,如果我要在 Meteor 中做同样的事情,它就行不通。这是我的代码:

Tickers.update({id: '3TKgHKkGnzgfwqYHY'}, {$pull: {'entries': {'id': '8171c4dbcc71052a8c6a38fb'}}});

我还尝试了以下方法:

Tickers.update('3TKgHKkGnzgfwqYHY', {$pull: {'entries': {'id': '8171c4dbcc71052a8c6a38fb'}}});

这些命令都没有给我错误,但它们不会从我的文档中删除任何内容。

有没有可能,$pull 命令没有得到正确支持,或者我在某处犯了错误?

提前致谢!

编辑: 我发现了这个问题,在我的描述中看不到,因为我已经简化了我的架构。在我的应用程序中,TickerEntries 中有一个附加属性 timestamp

TickerEntries = new SimpleSchema({
    id: {
        type: String,
        optional: true,
        autoValue: function () {
            if (!this.isSet) {
                return new Mongo.Collection.ObjectID()._str;
            }
        }
    },
    timestamp: {
        type: Date,
        label: 'Minute',
        optional: true,
        autoValue: function () {
            if (!this.isSet) { // this check here is necessary!
                return new Date();
            }
        }
    },
    text: {
        type: String,
        label: 'Text'
    }
});

感谢 Kyll 的提示,我创建了一个 Meteorpad 并发现 autovalue 函数导致了问题。

我现在将函数更改为以下代码:

autoValue: function () {
    if (!this.isSet && this.operator !== "$pull") { // this check here is necessary!
        return new Date();
    }
}

现在它正在工作。似乎,在拉取项目/对象的情况下返回自动值值,它取消拉取操作,因为该值未设置为返回值(因此时间戳属性保留旧值但未拉取)。

这是用于测试它的相应 Meteorpad(只需注释掉自动值函数中对运算符的检查):http://meteorpad.com/pad/LLC3qeph66pAEFsrB/Leaderboard

感谢大家的帮助,大家的帖子对我很有帮助!

【问题讨论】:

  • 我建议起草一个MeteorPad 来显示您的问题(创建数据库,添加架构,填充它,尝试删除并显示失败)。另一点:删除附加的模式是否会改变您的问题?如果不是,您可能希望将它们完全从问题中删除,因为现在我真的不知道模式是否具有任何重要性。最后,恭喜您帖子的格式和清洁度!如果您在问题中添加javascript 标签,它会自动为代码添加颜色。
  • 我建议你在某处犯了错误或配置错误或冲突。我提交的答案显示了一个完整的工作案例。如果有其他东西干扰$pull的预期行为,它应该有助于缩小您可能遇到的任何问题@
  • 修复了我们的问题 - 自动值阻止了 $pull。感谢您对@reini122 的全面提问和回答。
  • 澄清一下:我遇到了完全相同的问题,但我还必须在“自动值”上添加“if (!this.isSet && this.operator !== "$pull")” ”的“id”使一切正常。发现这一点真是太棒了!

标签: javascript mongodb meteor mongodb-query


【解决方案1】:

对于一个基本的流星应用程序,我称之为“双层”。如果您创建一个全新的项目并简单地定义集合,那么 $pull 运算符将按预期工作:

控制台:

meteor create tickets
cd tickets
meteor run

然后打开一个shell并插入你的数据:

meteor mongo

> db.tickets.insert(data)   // exactly your data in the question

然后只需生成一些基本的代码和模板:

tickers.js

Tickers = new Meteor.Collection("tickers");

if (Meteor.isClient) {

  Template.body.helpers({
    "tickers": function() {
      return Tickers.find({});
    }
  });

}

if (Meteor.isServer) {
  Meteor.startup(function () {
    // code to run on server at startup
  });
}

tickers.html

<head>
  <title>tickers</title>
</head>

<body>
  <h1>Welcome to Meteor!</h1>

  <ul>
    {{#each tickers}}
      {{> ticker}}
    {{/each}}
  </ul>

</body>

<template name="ticker">
  <li>
    {{_id}}
    <ul>
      {{#each entries}}
        {{> entry }}
      {{/each}}
    </ul>
  </li>
</template>

<template name="entry">
  <li>{{ id }} - {{text}}</li>
</template>

应用程序应该运行良好,所以在您的浏览器控制台中执行.update()(缩进阅读):

Tickers.update(
    { "_id": "ZcEvq9viGQ3uQ3QnT" },
    { "$pull": { "entries": { "id": "fc29774dadd7b37ee0dc5e3e" } }}
)

并且该项目从条目中删除并且页面在没有该项目的情况下被刷新。正如预期的那样,一切都过去了。

即使添加 SimpleSchemaCollection2 包,在这里也没有什么区别:

 meteor add aldeed:simple-schema
 meteor add aldeed:collection2

tickers.js

Tickers = new Meteor.Collection("tickers");

TickerEntries = new SimpleSchema({
  "id": {
    type: String,
    optional: true,
    autoValue: function() {
      if (!this.isSet) {
        return new Mongo.Collection.ObjectID()._str
      }
    }
  },
  "text": {
    type: String
  }
});

Tickers.attachSchema(
  new SimpleSchema({
    entries: { type: [TickerEntries] }
  })
);


if (Meteor.isClient) {

  Template.body.helpers({
    "tickers": function() {
      return Tickers.find({});
    }
  });

}

if (Meteor.isServer) {
  Meteor.startup(function () {
    // code to run on server at startup
  });
}

重新初始化数据并在浏览器控制台中运行相同的命令,一切都保持不变。

检查此操作或您自己操作中的任何输入错误或其他差异,以了解为什么这对您不起作用。

我强烈建议这样做,因为像这样的“重新开始”显示了预期的行为,如果您看到不同的行为,那么很可能是您安装的另一个插件存在问题。

但一般来说,这是可行的。

【讨论】:

  • 感谢这个干净而广泛的例子! :-)
  • @reini122 我真的希望这里有一些东西可以“解决”这个问题,但否则我的目的是展示我可以从你的问题中得到的基本包的响应。如果您发现冲突,请随时通知我错误报告。 StackOverflow cmets 可以稍后清理,但如果存在包冲突导致问题进行一些干预以解决问题,我有个人兴趣。
  • 是的,我已经解决了我的问题并使用解决方案编辑了我的原始问题。我希望这很清楚。我还添加了一个 Meteorpad 来模拟问题,但它确实是 SimpleSchema 的问题,因为在时间戳字段的情况下,自动值会阻止 pull 运算符工作,但 ID 字段中的类似代码不会破坏功能。
  • reini122,实际上对我来说,子模式 id 上的 autoValue 也破坏了 $pull 功能。用你的解决方法修复:)
【解决方案2】:

顺便提一下,如果其他人正在寻找答案。

如果您在 SimpleSchema 中使用,您有两种选择: 数组字段应标记为可选

arr: {
 type:Array,
 optional:true
}

或者在更新查询中使用getAutoValues: false

Coll.update({}, {$pull: {arr: ''}}, {getAutoValues: false});

【讨论】:

    猜你喜欢
    • 2021-04-01
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 2017-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多