Meteor、MongoDB通过订阅获取部分数组

Posted

技术标签:

【中文标题】Meteor、MongoDB通过订阅获取部分数组【英文标题】:Meteor, MongoDB get part of array through subscription 【发布时间】:2014-10-10 13:46:00 【问题描述】:

我有一个关于如何使用 MongoDB 和 MeteorJS 获取数组的某个元素的问题。我有以下用户文档架构:

    bankList:[
       
          id: "34567890987654345678",
          name: "xfgchjbkn",
          type: "credit"
       ,
       
          id: "09876543456789098767"
          name: "65789876t8",
          type: "debit"
       
    ]

我首先只订阅了数组中的部分字段,特别是我收集了所有 id 的列表。然后我有一个编辑屏幕,它应该订阅数组中具有匹配 id 的特定元素的所有字段。我不想只公开单个元素的数组的其余部分。目前,我使用以下方法首先收集一个仅包含 id 的列表:

   Meteor.users.find(_id: this.userId,
                        fields:'bankList.id': 1);

以及下面的发布订阅方法来获取特定元素的信息:

出版:

  Meteor.publish("userBankAdvanced", function(bankId)
      check(bankId,String);
      if(this.userId)
           return Meteor.users.find(_id:this.userId,"bankList.id": bankId, 'bankList.$': 1);
      else
           this.ready();
      
  );

订阅:

  this.route('edit_account', 
        path: '/edit/account/',
        waitOn: function()
              if(Session.get("bankId"))
                    return Meteor.subscribe('userBankAdvanced',Session.get("bankId"));
        
        return null;
        ,
        data: function()
              if(Session.get("bankId"))
                return Meteor.users.findOne();
        
        return null;
        ,
        onBeforeAction: function()
              beforeHooks.isRevise(Session.get("bankId"));
        
  );

订阅方法返回包含所有信息的数组的所有元素。 例如,我想要这个(不是包含所有信息的整个列表):

       bankList:[
       
          id: "34567890987654345678",
          name: "xfgchjbkn",
          type: "credit"
       ]

【问题讨论】:

在 $elemmatch 投影上查看 mongo 文档。 是的,我使用 $elemMatch 还是 $ 位置索引都没关系。 我不明白。您是否在发布函数中使用 $elemMatch 或 $ 并且仍将完整数组发送到客户端? 查看字段说明符的流星集合文档。 字段:'bankList.$':1。 【参考方案1】:

不走运,在流星中,“字段”选项只能工作一层。换句话说,没有包含/排除子文档字段的内置方法。

但并非全部丢失。您可以随时手动完成

Meteor.publish("userBankAdvanced", function (bankId) 
  var self = this;
  var handle = Meteor.users.find(
    _id: self.userId, "bankList.id": bankId
  ).observeChanges(
    added: function (id, fields) 
      self.added("users", id, filter(fields, bankId));
    ,
    changed: function (id, fields) 
      self.changed("users", id, filter(fields, bankId));
    ,
    removed: function (id) 
      self.removed("users", id);
    ,
  );
  self.ready();
  self.onStop(function () 
    handle.stop();
  );
);

function filter(fields, bankId) 
  if (_.has(fields, 'bankList') 
    fields.bankList = _.filter(fields.bankList, function (bank) 
      return bank.id === bankId;
    );
  
  return fields;

编辑我更新了上面的代码以匹配问题要求。事实证明,Carlos 的答案也是正确的,而且当然要简单得多,所以我建议使用那个答案。

【讨论】:

来自 field specifiers 上的流星文档,“客户端上尚不提供 $ 和 $elemMatch 等字段运算符。”。这意味着它们在服务器端工作,不是吗? 在应用程序中测试,$ 位置运算符和$elemMatch 在服务器上的fields 选项中工作以查找子文档。有关语法,请参阅此问题的 other answer。 好吧,你是对的。这实际上在服务器上工作。我不知道它已经实现了,很抱歉误导了你。 @user728291 我更新了答案,因为一开始我误解了你想要实现的目标。不过,Carlos 的回答更好。【参考方案2】:

看起来您只是在“userBankAdvanced”发布函数中缺少“字段”说明符。我写了一个test in meteorpad using your example,它似乎工作正常。为简单起见,银行 ID 是硬编码的。

所以不是

return Meteor.users.find(_id:this.userId,"bankList.id": bankId, 'bankList.$': 1);

尝试使用

return Meteor.users.find(_id:this.userId,"bankList.id": bankId, fields: 'bankList.$': 1);

【讨论】:

这个答案基本上救了我的命。有没有可能与 findAndModify() 一起使用(它本身就是一个附加组件:( 包)。另外 - 你知道为什么这种语法与“预期的”mongo 文档coll.find(,'array':$elemMatch: 'key':'value') 如此不同吗

以上是关于Meteor、MongoDB通过订阅获取部分数组的主要内容,如果未能解决你的问题,请参考以下文章

Meteor 集合获取返回空数组但已订阅

Meteor:发布/订阅问题

MongoDB & Meteor - 推入嵌套数组的查询不起作用,没有抛出错误

Meteor / MongoDB - 如何证明数组中的任何项目是不是等于特定值,而不是在“真”的情况下从另一个数组中提取项目?

Meteor mongodb:如何获取第 N 条记录?

Meteor mongodb:如何获取第 N 条记录?