流星 - 具有“独特”功能的自动完成功能?

时间:2015-05-04 10:16:51

标签: meteor

我有一个收集歌曲,其中包含以下格式的数据:

{artist:"Dream Theater", title: "Pull me under"}, {artist:"Dream Theater", title: "Finally free"}

我正在使用mizzao-autocomplete包有超过5000个条目,所以我定义需要服务器端自动完成。 在服务器上我发布了集合:

Meteor.publish("autocompleteArtists", function(selector, options) {
  Autocomplete.publishCursor(Songs.find(selector, options), this);
  this.ready();
});

客户订阅如下:

Template.home.helpers({
    settings: function() {
        return {
            position: "top",
            limit: 5,
            rules: [{
                collection: 'Songs',
                subscription: 'autocompleteArtists',
                field: "artist",
                template: Template.songItem
            }]
        };
    }
});

我应该在settings()函数中同时拥有收集和订阅吗?

最后一部分,客户端模板:

{{> inputAutocomplete settings=settings id="artistInput" type="text" placeholder="Artist" length="20"}}

我的目的是寻找一位艺术家,当我选择它时,订阅一个简单的服务器发布,它返回属于该艺术家的所有歌曲。问题是,如果我有多个具有相同艺术家的条目,当然,结果列表会多次显示艺术家。我需要以某种方式发布一个“独特”的出版物,它将归还所有艺术家,但Meteor中没有这样的功能。我找到了一些实现聚合和不同的东西,但是我没有看到如何使用Autocomplete publishCursor函数...我的临时解决方案是反规范化并添加一个Artists集合,但我不应该这样做。

有更简单的方法吗?

1 个答案:

答案 0 :(得分:1)

如果要在服务器上执行自动完成,则似乎需要subscriptioncollection参数。

不幸的是,正如您所注意到的那样,实施唯一性并不是一个好方法。您可以使用聚合,但除非它返回游标,否则它看起来不像您想要的那样(例如,Meteorhacks:聚合不会)。

一个(简单?)方法是识别每个艺术家的一个实例并标记它(autocomplete: true);然后您可以使用filter选项过滤autocomplete = true的位置。如果人们手动输入歌曲,这很容易做到:

Meteor.methods({
  insertSong: function(song, artist) { 
    var entry = {title: song, artist: artist, autocomplete: false};
    if (Songs.find({artist: artist}).count() === 0) { entry.autocomplete = true; }
    Songs.insert(entry);
  }
});

您的rules只需要包含filter对象:

...
rules: [{
            collection: 'Songs',
            subscription: 'autocompleteArtists',
            field: "artist",
            template: Template.songItem,
            filter: {autocomplete: true}
        }]
...

然后您需要另一个发布/订阅来实际显示相关艺术家的歌曲:

// Server
Meteor.publish("songsByArtist", function(artist) { 
  return Songs.find({artist: artist});
});

// Client
Template.home.events({ // listen for selection and subscribe
  "autocompleteselect input": function(event, template, doc) {

   Meteor.subscribe("songsByArtist", doc.artist);
  }
});

// And you can iterate like so with a helper:
songsToDisplay: function() { 
  return Songs.find();
}

<!-- HTML -->
{{#each songsToDisplay}}
  {{> songAndArtist}}
{{/each}}

你可以在这个问题上玩MeteorPad.抱歉,我想不出更好的方法。