通过Meteor从阵列中拉出一个条目 [英] Pull an entry from an array via Meteor

查看:137
本文介绍了通过Meteor从阵列中拉出一个条目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



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

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

TickerEntries = new SimpleSchema({
id:{
type:String,
autoform:{
type:hidden,
label:false,
readonly:true
},
可选:true,
autoValue:function(){
if(!this.isSet){
返回新的Mongo.Collection.ObjectID()._ str;
}
}
},
text:{
type:String,
label: '文字'
}
};

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

  {
_id:ZcEvq9viGQ3uQ3QnT,
条目:[
{
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'}}}); 

我也尝试了以下内容:



< pre class =lang-js prettyprint-override> Tickers.update('3TKgHKkGnzgfwqYHY',{$ pull:{'entries':{'id':'8171c4dbcc71052a8c6a38fb'}}});

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



是否有可能, $ pull 命令不正确支持或我在某处犯了错误?



提前致谢!



编辑:
我发现了这个问题,在我的描述中可以看到,因为我简化了我的架构。在我的应用程序中, TickerEntries 中还有一个额外的属性 timestamp



< pre class =lang-js prettyprint-override> TickerEntries = new SimpleSchema({
id:{
type:String,
optional:true,
autoValue:function(){
if(!this.isSet){
return new Mongo.Collection.ObjectID()._ str;
}
}
} ,
时间戳:{
类型:日期,
标签:'分钟',
可选:true,
autoValue:function(){
if( !this.isSet){//这里的检查是必要的!
返回新的Date();
}
}
},
text:{
类型:字符串,
标签:'文字'
}
});

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



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

  autoValue:function(){
if(!this.isSet&& this.operator! ==$ pull){//这里的检查是必要的!
返回新的Date();
}
}

现在它正在运作。看来,在拉动项目/对象的情况下返回autovalue值,它会取消拉取操作,因为该值未设置为返回值(因此timestamp属性保留旧值但不拉)。



这是相应的Meteorpad测试它(只是在autovalue函数中注释掉操作符的检查): http://meteorpad.com/pad/LLC3qeph66pAEFsrB/Leaderboard



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

解决方案

对于基本的流星应用程序,我称之为上下铺 就此而言。如果您创建一个全新的项目并只是定义该集合,那么 $ pull 运算符按预期工作:



控制台:

  meteor create tickets 
cd tickets
meteor run

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



< pre class =lang-js prettyprint-override> meteor mongo

> db.tickets.insert(data)//完全是问题中的数据

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



tickers.js

  Tickers = new Meteor.Collection(tickers); 

if(Meteor.isClient){

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

}

if(Meteor.isServer){
Meteor.startup(function(){
//在启动时在服务器上运行的代码
});
}

tickers.html

 < head> 
< title>代码< / title>
< / head>

< body>
< h1>欢迎来到Meteor!< / h1>

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

< / body>

< template name =ticker>
< li>
{{_id}}
< ul>
{{#each entries}}
{{>输入}}
{{/ each}}
< / ul>
< / li>
< / template>

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

应用程序运行正常,因此在浏览器控制台中执行。 update()(缩进阅读):

  Tickers.update (
{_ id:ZcEvq9viGQ3uQ3QnT},
{$ pull:{entries:{id:fc29774dadd7b37ee0dc5e3e}}}

此项目将从条目中删除,页面将刷新而不包含该项目。所以一切都消失了,就像预期一样。



甚至添加 SimpleSchema Collection2 软件包在这里没有区别:

  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: {
类型:字符串
}
});

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


if(Meteor.isClient){

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

}

if(Meteor.isServer){
Meteor.startup(function(){
//在启动时在服务器上运行的代码
});
}

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



检查您自己的操作中的这个或任何输入错误或其他差异,以找出为什么这对您不起作用的线索。



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



但一般来说,这都有效。


I've the following (simplified) SimpleSchema schema in my Meteor 1.1.0.2 app:

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'
    }
};

In the database I do have the following entries:

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

I'd like to remove one entry in the entries array specified by an ID.

If I execute the following command in the meteor-mongodb-shell it works without problems:

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

But the problem is, that if I'm going to do the same from within Meteor, it doesn't work. Here's my code:

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

I've also tried the following:

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

None of these commands give me an error, but they don't remove anything from my document.

Could it be possible, that the $pull command isn't supported properly or do I have made a mistake somewhere?

Thanks in advance!

EDIT: I've found the problem, which couldn't be seen in my description, because I've simplified my schema. In my app there's an additional attribute timestamp in TickerEntries:

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'
    }
});

Thanks to the hint from Kyll, I've created a Meteorpad and found out, that the autovalue function is causing the problems.

I've now changed the function to the following code:

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

And now it is working. It seems, that returning a autovalue-value in the case of pulling an item/object, it cancels the pull operation, as the value isn't set to the returned value (so the timestamp attribute keeps the old value but isn't pulled).

Here's the according Meteorpad to test it (simply comment out the check for the operator in the autovalue function): http://meteorpad.com/pad/LLC3qeph66pAEFsrB/Leaderboard

Thank you all for your help, all your posts were very helpful to me!

解决方案

For a basic meteor application, I call "bunk" on this. If you create a brand new project and simply define the collection, then the $pull operator works as expected:

Console:

meteor create tickets
cd tickets
meteor run

Then open up a shell and insert your data:

meteor mongo

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

Then just produce some basic code and template:

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>

The application should be running fine, so in your browser console do the .update() (indented for reading):

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

And the item is removed from entries and the page is refreshed without the item. So all gone, just as expected.

Even adding the SimpleSchema and Collection2 packages, makes no difference here:

 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
  });
}

Re-initialize the data and run the same command in the browser console and everything stays the same.

Check this or any typing mistakes in your own operations or other differences for a clue as to why this does not work for you.

I would suggest this strongly, as "starting fresh" like this shows the expected behavior, and if you are seeing different behavior then it is likely an issue with another plugin you have installed.

But generally, this works.

这篇关于通过Meteor从阵列中拉出一个条目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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