动态创建新的Meteor集合

4

是否可以动态创建新的Meteor集合? 我想根据一些路径名(我想是全局变量),例如foo_barbar_bar来创建集合,这取决于它。我可以在整个应用程序中访问该变量。
类似以下内容:

var prefix = window.location.pathname.replace(/^\/([^\/]*).*$/, '$1');
var Bar = new Meteor.Collection(prefix+'_bar');

这里的问题是我应该从URL获取我的prefix变量,所以如果我在if (Meteor.isClient)之外声明它,我会得到一个错误:ReferenceError: window is not defined。有可能做到这样吗? 编辑:使用Akshat答案的第一次迭代,我项目的js:http://pastie.org/6411287

尽管有可能,但这并不意味着这是一个好主意:MongoDB在集合数量方面有一些限制,它不适合通过集合进行扩展,因此如果您的动态集合变得很大,您可能会遇到瓶颈。 - MrE
2个回答

4

我不太确定这个方法是否可行:

你需要将其拆分为两部分,第一部分加载之前设置的集合(在客户端和服务器端都要加载)。

var collections = {};
var mysettings = new Meteor.Collection('settings') //use your settings

//Startup
Collectionlist = mysettings.find({type:'collection'});

Collectionlist.forEach(function(doc) {
    collections[doc.name] = new Meteor.Collection(doc.name);
})'

您需要在服务器上添加集合:

Meteor.methods({
    'create_server_col' : function(collectionname) {
       mysettings.insert({type:'collection', name: collectionname});
       newcollections[collectionname] = new Collection(collectionname);
       return true;
    }
});

您需要在客户端创建它们:

//Create the collection:

Meteor.call('create_server_col', 'My New Collection Name', function(err,result) {
    if(result) {
        alert("Collection made");
    }
    else
    {
        console.log(err);
    }
}

再次强调,这些都未经过测试,我只是试图给出一些帮助,希望能够奏效。

编辑

也许下面的代码可以工作,我已经添加了一些检查来先看看集合是否存在。在你使用它对上面的代码进行错误排序之前,请运行meteor reset

var collections = {};
var mysettings = new Meteor.Collection('settings')

if (Meteor.isClient) {
  Meteor.startup(function() {
    Collectionlist = mysettings.find({type:'collection'});

    Collectionlist.forEach(function(doc) {
        eval("var "+doc.name+" = new Meteor.Collection("+doc.name+"));
    });
  });
  Template.hello.greeting = function () {
    return "Welcome to testColl.";
  };

  var collectionname=prompt("Enter a collection name to create:","collection name")

  create_collection(collectionname);

  function create_collection(name) {
    Meteor.call('create_server_col', 'tempcoll', function(err,result) {
        if(!err) {
            if(result) {
                //make sure name is safe
                eval("var "+name+" = new Meteor.Collection('"+name+"'));
                alert("Collection made");
                console.log(result);
                console.log(collections);
            } else {
                alert("This collection already exists");
            }
        }
        else
        {
            alert("Error see console");
            console.log(err);
        }
    });
  }
}

if (Meteor.isServer) {
  Meteor.startup(function () {
    // code to run on server at startup
    Collectionlist = mysettings.find({type:'collection'});

    Collectionlist.forEach(function(doc) {
        collections[doc.name] = new Meteor.Collection(doc.name);
    });
  });

  Meteor.methods({
    'create_server_col' : function(collectionname) {
       if(!mysettings.findOne({type:'collection', name: collectionname})) {
        mysettings.insert({type:'collection', name: collectionname});

        collections[collectionname] = new Meteor.Collection(collectionname);

        return true;
       }
       else
       {
        return false; //Collection already exists
       }
    }
  });
}

同时确保你的名称已进行了JavaScript转义。


谢谢你的帮助 :) 我稍微尝试了一下你的代码,发现了几个问题。首先,我必须更改一些笔误,我的新代码在这里。运行后,我可以看到警报,因此集合显然已创建,但是当我尝试查询我的新集合时,我会收到“ReferenceError:tempcoll未定义”的错误消息。此外,在警报出现后,如果我尝试在控制台中查看我的“collections”对象,则会发现它为空。 - errata
最后,如果我用代码中相同的集合名称刷新页面,我会得到“调用方法'create_server_col'时出现异常错误:已经定义了名为'/tempcollx/insert'的方法”。所以我想我应该检查是否已经存在具有相同名称的集合。我确实相信你的代码非常接近,也许有些微不足道的东西,但是我对mongodb没有太多经验,所以我不确定如何进一步调试...谢谢再次帮助 :) - errata
如果可以的话,我会使用您粘贴的代码来回答,我可以编辑您的问题以包含您的gist链接吗? - Tarang
好的,抱歉让您久等了,这个应该更接近您想要的了。 - Tarang

3

事情变得更加容易了:

var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db;
db.createCollection("COLLECTION_NAME", (err, res) => {
    console.log(res);
});

在您的服务器方法中运行此操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接