按名称获取 Meteor 集合

Posted

技术标签:

【中文标题】按名称获取 Meteor 集合【英文标题】:Get Meteor collection by name 【发布时间】:2012-06-14 14:09:21 【问题描述】:

假设我写:

new Meteor.Collection("foos");
new Meteor.Collection("bars");

是否有用于按名称访问这些集合的 API?类似于Meteor.Collection.get(name),其中name"foos""bars"?我知道我可以写类似的东西

var MyCollections = 
    foos: new Meteor.Collection("foos");
    bars: new Meteor.Collection("bars");

然后使用MyCollections[name],但如果存在,我更愿意使用现有的 API。

【问题讨论】:

【参考方案1】:

与其看,我一直在做:

Foos = new Meteor.Collection("foos");

或者可能把它放在另一个对象中。我还没有真正制作 Collections 集合对象。

【讨论】:

好吧,我知道我能做到。但是我有大量的集合共享相同的代码,所以我想按名称引用它们。【参考方案2】:

据我在collection.js 源中看到的,一旦它已经在服务器上初始化,API 目前无法按名称获取现有集合。添加该功能可能并不难。

那么,为什么不分叉 Meteor 并提交补丁或创建一个智能包并分享它,我敢肯定还有其他人想要相同的功能。

【讨论】:

接受这个答案,因为它基于 the source 的阅读。 Meteor.connection._mongo_livedata_collections找到它 @nepjua 不是正确的集合,尝试在 javascript 控制台中插入它,您会看到数据确实插入到客户端但没有发送到服务器。跨度> 这个答案已经过时了:现在有办法,至少在客户端。看到这个答案:***.com/a/37938322/14637【参考方案3】:

注意它们有一个返回值,所以你可以这样做

var Patterns = new Meteor.Collection("patterns");

并使用Patterns无处不在

并且当您需要订阅服务器更新时,请将"patterns" 提供给Meteor.subscribe()


如果您对多个集合有相同的代码,那么从软件工程的角度来看,您做错了什么的可能性很高;为什么不使用带有 type 字段的单个集合(或其他区分文档的内容)并使用它而不是使用多个集合?

【讨论】:

很高兴指出 OP 中似乎明显的遗漏,new Mongo.Collection 调用返回一个集合对象。另一方面,如果发布函数使用不同的名称,则仅向Meteor.subscribe() 提供集合名称可能不起作用。详情请见Understanding Meteor publish/subscribe。【参考方案4】:
var bars = new Meteor.Collection("foos");

根据collection.js 所做的判断,我们用来实例化集合对象的行打开了与数据库的连接,并查找与我们提供的名称匹配的集合。因此,在这种情况下,建立了一个连接,并且集合“foos”被绑定到 Meteor.Collection 对象“bars”。请参阅 mongo-livedata 包中的 collection.jsremote_collection_driver.js

与 MongoDB 一样,尽管您可以,但您不必显式创建集合。如 MongoDB 文档中所述:

在插入第一个文档时会创建一个集合。

所以,我认为你所追求的就是你已经拥有的——除非我完全误解了你的意图。

【讨论】:

【参考方案5】:

正如其他人所提到的,如果不在创建时保存它,似乎没有办法获取包装的 Meteor.Collection 对象。

但至少有一种方法可以列出所有创建的集合,并实际访问相应的 Mongo LocalCollection 对象。它们可从任何 Meteor Collection 对象中获得,因此为了保持通用性,您可以为此创建一个虚拟集合。使用这样的方法(CoffeeScript):

dummy = new Meteor.Collection 'dummy'
getCollection = (name) ->
  dummy._driver.collections[name]

这些对象确实有所有的 find、findOne、update 等方法,甚至还有一些 Meteor 似乎没有公开的方法,比如看起来很有趣的 pauseObservers 和 resumeObservers。但我没有尝试直接摆弄这个 mongo LocalCollection 引用来了解它是否会相应地更新服务器集合。

【讨论】:

注意:.collections 仅在客户端上可用,作为 LocalCollectionDriver (github.com/meteor/meteor/blob/master/packages/mongo-livedata/…) 的一部分。因此,这种方法将为您提供发布给客户端的所有集合,但不一定是所有集合。【参考方案6】:

您始终可以推出自己的自动收集吸气剂。

假设您有几个名为“Businesses”和“Clients”的集合。将每个引用放入一些“集合”对象并注册一个 Handlebars 助手以通过集合[“名称”]访问这些“集合”。

即把这样的东西放在客户端main.js

collections = collections || ;
collections.Businesses = Businesses;
collections.Clients = Clients;

Handlebars.registerHelper("getCollection", function(coll) 
  return  collections[coll].find();
);

然后在您的 html 中,只需按名称引用集合:

#each getCollection 'Businesses'
  <div> Business: _id </div>
/each

#each getCollection 'Clients'
  <div> Client: _id </div>
/each

看,不再需要通用的“列出所有记录”样板 js!

【讨论】:

【参考方案7】:

基于 Shane Donelley 的 mongoinspector https://github.com/shanedonnelly1/mongoinspector

getCollection = function (string) 
for (var globalObject in window) 
    if (window[globalObject] instanceof Meteor.Collection) 
        if (globalObject === string) 
            return (window[globalObject]);
            break;
        ;        
    

return undefined; // if none of the collections match
;

【讨论】:

你可以在服务器上做同样的事情,使用 this 而不是 window .代码相同,只需将window替换为this即可从全局命名空间中获取集合对象。 在全局上下文之外,在严格模式下,使用var globals = Function('return this')(); 获取对全局对象的引用。所以将代码中的window替换为globals 此模式由meteor-autocomplete使用。 我不明白为什么你循环window对象而不是做:getCollection = function (string) return (window &amp;&amp; window[string] &amp;&amp; window[string] instanceof Meteor.Collection) ? window[string] : undefined; 【参考方案8】:

我刚刚找到了那个包:https://github.com/dburles/mongo-collection-instances/

它可以让你

Foo1 = new Mongo.Collection('foo'); // local
Foo2 = new Mongo.Collection('foo',  connection: connection );

Mongo.Collection.get('foo') // returns instance of Foo1

Mongo.Collection.get('foo',  connection: connection ); 
// returns instance of Foo2

希望对你有帮助

【讨论】:

注意,这个包不再需要,因为现在检索现有集合是一个内置功能。 @malhal 你有链接显示,如何在当前版本中做到这一点?【参考方案9】:

此功能于 2016 年 2 月添加到 Meteor:"Provide a way to access collections from stores on the client"

它是这样工作的:

Meteor.connection._stores['tasks']._getCollection();

我使用它如下使用javascript控制台测试插入:

Meteor.connection._stores['tasks']._getCollection().insert(text:'test');

对于插入,它需要insecure 包仍被安装,否则会收到拒绝访问消息。

【讨论】:

是否可以从服务器端和客户端调用它?我试过这段代码,总是得到 TypeError: Cannot read property '_stores' of undefined 在服务器端。【参考方案10】:

使用https://github.com/dburles/mongo-collection-instances,您可以使用Mongo.Collection.get('collectionname')

请注意,您插入的参数与创建集合时使用的参数相同。所以如果你使用const Products = new Mongo.Collection('products'),那么你应该使用get('products')(小写)。

【讨论】:

以上是关于按名称获取 Meteor 集合的主要内容,如果未能解决你的问题,请参考以下文章

Meteor - 发布按个性化分数排序的集合

如何按插入时间对 Meteor 集合进行排序?

在 Meteor 中获取集合的索引列表

Meteor - 如何在 MongoDB 集合中查找/获取对象并使用方法将其推送到另一个集合中?

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

Meteor Shopify API:通过集合 ID 将元字段发布到集合