如何使用 Typeahead 和 Bloodhound 一次性使用多个数据集?
How to use multiple datasets in one go with Typeahead and Bloodhound?
我正在尝试使用 Typeahead/Bloodhound 进行建议和搜索。为了简单起见,假设我有两种类型的模型对象 - Country 和 City.
public class Country
{
public string Name { get; set; }
}
(服务器端在 ASP.NET,但这与问题无关)。
城市实际上与国家相同,只是名称不同。
无论如何,在造型之前,我希望最终结果看起来像这样:
(如果不明显,我在文本框中写了"AL",其余字母构成第一个建议)
我可以通过使用多个 Bloodhounds 轻松实现此目的:
var countries = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 5,
remote: {
url: 'http://localhost:5000/api/countries/%QUERY',
wildcard: '%QUERY'
}
});
var cities = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 5,
remote: {
url: 'http://localhost:5000/api/cities/%QUERY',
wildcard: '%QUERY'
}
});
和多个要提前输入的输入对象:
$('#remote .typeahead').typeahead(null,
{
name: 'countries',
display: 'name',
source: countries,
templates: {
empty: [
'<div class="empty-message">',
'unable to find any countries that match the current query',
'</div>'
].join('\n'),
suggestion: Handlebars.compile('<div><strong>{{name}}</strong></div>'),
header: '<h2>Countries</h2>'
}
},
{
name: 'cities',
display: 'name',
source: cities,
templates: {
empty: [
'<div class="empty-message">',
'unable to find any cities that match the current query',
'</div>'
].join('\n'),
suggestion: Handlebars.compile('<div><strong>{{name}}</strong></div>'),
header: '<h2>Cities</h2>'
}
});
但是,在我的真实场景中,我有大约 10 个数据集。创建 10 个单独的查询,结合 JSON serialization/deserialization 可能会当场杀死我的服务器,尤其是有多个用户时。
我更喜欢复合 DTO:
public class CompositeSearchResult
{
public List<Country> Countries { get; set; }
public List<City> Cities { get; set; }
//... and many others
}
...同时使用 Bloodhound 以某种方式处理客户端上的复杂对象。这可能吗?
我做到了!
首先我发现,Bloodhound 缓存是智能的 - 所以如果它已经进行了搜索查询,它将不再使用网络 - 而是会在缓存中查找。
所以这意味着如果两个数据集的URL相同,则查询只在服务器上执行一次,然后将结果集缓存并供所有猎犬使用。
回到简单的国家+城市示例,它应该是这样的:
var countries = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 5,
remote: {
url: 'http://localhost:5000/api/compositesearch/%QUERY',
wildcard: '%QUERY',
transform: function(d) {
return d.countries;
}
}
});
var cities = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 5,
remote: {
url: 'http://localhost:5000/api/compositesearch/%QUERY',
wildcard: '%QUERY',
transform: function(d) {
return d.cities;
}
}
});
这两种情况的唯一区别是远程设置中的"transform"功能。
然后,通过使用问题中完全相同的 CompositeSearch 对象,我可以一次检索两个数据集(与屏幕截图中的基本相同),而不是两次 - 通过浏览器的“网络”选项卡确认:)
我正在尝试使用 Typeahead/Bloodhound 进行建议和搜索。为了简单起见,假设我有两种类型的模型对象 - Country 和 City.
public class Country
{
public string Name { get; set; }
}
(服务器端在 ASP.NET,但这与问题无关)。
城市实际上与国家相同,只是名称不同。
无论如何,在造型之前,我希望最终结果看起来像这样:
(如果不明显,我在文本框中写了"AL",其余字母构成第一个建议)
我可以通过使用多个 Bloodhounds 轻松实现此目的:
var countries = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 5,
remote: {
url: 'http://localhost:5000/api/countries/%QUERY',
wildcard: '%QUERY'
}
});
var cities = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 5,
remote: {
url: 'http://localhost:5000/api/cities/%QUERY',
wildcard: '%QUERY'
}
});
和多个要提前输入的输入对象:
$('#remote .typeahead').typeahead(null,
{
name: 'countries',
display: 'name',
source: countries,
templates: {
empty: [
'<div class="empty-message">',
'unable to find any countries that match the current query',
'</div>'
].join('\n'),
suggestion: Handlebars.compile('<div><strong>{{name}}</strong></div>'),
header: '<h2>Countries</h2>'
}
},
{
name: 'cities',
display: 'name',
source: cities,
templates: {
empty: [
'<div class="empty-message">',
'unable to find any cities that match the current query',
'</div>'
].join('\n'),
suggestion: Handlebars.compile('<div><strong>{{name}}</strong></div>'),
header: '<h2>Cities</h2>'
}
});
但是,在我的真实场景中,我有大约 10 个数据集。创建 10 个单独的查询,结合 JSON serialization/deserialization 可能会当场杀死我的服务器,尤其是有多个用户时。
我更喜欢复合 DTO:
public class CompositeSearchResult
{
public List<Country> Countries { get; set; }
public List<City> Cities { get; set; }
//... and many others
}
...同时使用 Bloodhound 以某种方式处理客户端上的复杂对象。这可能吗?
我做到了!
首先我发现,Bloodhound 缓存是智能的 - 所以如果它已经进行了搜索查询,它将不再使用网络 - 而是会在缓存中查找。
所以这意味着如果两个数据集的URL相同,则查询只在服务器上执行一次,然后将结果集缓存并供所有猎犬使用。
回到简单的国家+城市示例,它应该是这样的:
var countries = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 5,
remote: {
url: 'http://localhost:5000/api/compositesearch/%QUERY',
wildcard: '%QUERY',
transform: function(d) {
return d.countries;
}
}
});
var cities = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 5,
remote: {
url: 'http://localhost:5000/api/compositesearch/%QUERY',
wildcard: '%QUERY',
transform: function(d) {
return d.cities;
}
}
});
这两种情况的唯一区别是远程设置中的"transform"功能。
然后,通过使用问题中完全相同的 CompositeSearch 对象,我可以一次检索两个数据集(与屏幕截图中的基本相同),而不是两次 - 通过浏览器的“网络”选项卡确认:)