按名称获取 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.js
和 remote_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 && window[string] && 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 集合的主要内容,如果未能解决你的问题,请参考以下文章