Algolia和使用instantsearch.js从你的脚本中为Shopify服务
"好的艺术家会复制,伟大的艺术家会偷窃"。- 史蒂夫-乔布斯
灵感来自于 pimoroni.com 我想在我们的网店上实现一个类似的搜索。 buyzero.de buyzero.de目前是由Shopify提供的。
搜索在你输入时显示结果--在主页上,动态地取代先前显示的内容。非常酷,非常有用--而且非常、非常快(谢谢 Algolia!)
由于我对Algolia的现有文件感到困惑,而且他们的入职服务也不是很有帮助,所以我不得不自己想办法,并通过大量的谷歌搜索来解决这些问题。
这是我实施Algolia的经验总结。我是在一天之内完成的,单次编码时间约为12-14小时。
建议的准备工作:将开发代码注入你的页面中
我建议使用谷歌浏览器的扩展程序 谭家驹 用于在开发时从你的本地硬盘注入CSS和Javascript。
要做到这一点,你必须为Tampermonkey启用文件访问。打开。
单击 "详细信息",并将 "允许访问文件URL "切换为 "允许"。
在Tampermonkey中创建以下新的用户脚本。
// ==UserScript== // @名称Algolia-Inject // @namespace https://pi3g.com/ // @版本 0.5 // @description 注入本地文件来测试Algolia! // @作者 Maximilian Batz // @grant GM_getResourceText // @授予GM_addStyle // @noframes // @include https://buyzero.de/* // @resource YOUR_CSS file://D:\algolia_jr.css // @require file:/D:\algolia_jr.js // ==/UserScript== var my_css = GM_getResourceText("YOUR_CSS")。 GM_addStyle(my_css);
解释一下。
- 你必须授予getResourceText和addStyle,以便能够访问和注入CSS文件。
- noframes是指在Shopify明显加载的框架中不执行第二次,这也符合域名的要求。
- include -> 将在buyzero.de上匹配。你可能想改变这一行
- 用于导入CSS文件的资源。提供路径...在Linux中可能是 file:///home/whatever/whatever - 注意三条正斜杠
- require - 包括你的javascript文件
- userscript:这是用于添加CSS文件的用户脚本。
添加Algolia代码
随着 "如何发展 "这一点的结束。 这是我的代码,作为样本代码放在一个漂亮的小ZIP文件中。.
请不要从这个博客复制粘贴,因为我不确定,WordPress是否会破坏代码的格式......使用ZIP文件中的.js来复制。
请注意,Algolia的依赖性/JavaScript文件已经安装在我们的Shopify主题中 - 通过安装Algolia Shopify插件。我们的数据存储也已经设置好了,等等。Algolia过去(现在也是)已经在你输入搜索框的时候以下拉方式提供搜索结果。
我将带领你完成代码的重要部分。
一旦文档准备好,我们就启动aj_setup(),以注入我们的新搜索功能。
请注意,我在这个脚本中使用aj作为我的函数和id的前缀。你可以使用任何你喜欢的东西,这不是Algolia的要求。
容器
在aj_setup()中,我为搜索结果设置了一个新的容器(把它直接包含在你的主题文件中可能是更好的做法--对于开发来说,这更容易)。
这是搜索的HTML部分
$(".main-content").before('<div id="aj-search-container" class="aj-main-content full-width"><div class="background"><div class="pattern"><div class="container"><div class="row"><div class="col-md-12"><div class="row"><div class="col-md-12 center-column content-without-background">'+
""+
"<h1>这类结果是毛利。 <span id='sc-query'></span></h1>" +
""+"+
""+
""+
""+
""+
"
""+"+
""+
""+
""+
"</DIV" +
"
'</div></div></div></div></div></div></div></div>'
);
- 我给它的ID aj-search-container。 能够显示/隐藏整个搜索容器的结果
- 大部分部门的人,包括 容器 是与我们目前的主题兼容的造型所必需的--根据需要使用
- sc-query 用于反映用户当前输入的搜索,以显示系统代表他动态地更新结果(有代码可以做到这一点--继续阅读)。
- aj-right-container 包含过滤器以获得搜索的 "面"。用户可以选择一个或几个品牌来显示,产品类别,我们还包括一个价格过滤器。
- aj-clear-all 将包含一个清除分面的链接--以返回所有符合用户查询的结果
- aj-left-container 包含搜索结果。aj-stats将包含关于搜索的统计数据(搜索结果+搜索时间),aj-search-results将包含结果,aj-search-pagination将包含分页。
命题模板
同样,这可能会直接进入你的页面,而不是通过Javascript注入。
$(".main-content").before('+')
'+
' <div class="aj-hit">'+
' <div class="aj-hit-image">'+
' <a href="/zh/{{product_link}}/"><img src="{{image}}" alt="{{title}}"></a>'+
' </div>'+
' <div class="aj-hit-content">'+
' <div class="aj-hit-title"><a href="/zh/{{product_link}}/">{{_highlightResult.title.value}}{{variant_title}}。</a></div>'+
'<p class="aj-hit-description">{{_highlightResult.body_html_safe.value}}。 <a href="/zh/{{product_link}}/">"mehr</a></p>'+
'<p class="aj-hit-sku"><a href="/zh/{{product_link}}/">{{sku}}</a></p>'+
' <div class="aj-hit-bottominfos">' +
' <div class="aj-hit-price">{pos(190,5)}}价格€</div>' +
' <div class="aj-hit-stock">{{inventory_quantity}}auf Lager </div>'+
' <div class="aj-hit-link"><a href="/zh/{{product_link}}/">产品介绍</a></div>'+
' </div>'+
'</div>'+
'
' +
'</div>'+
''+
'');这个模板是作为 "脚本 "插入的。这是Algolia文档中推荐的方式。
它用于呈现一个搜索结果,或命中。
在这里,在里面 aj-hit 我们有。
- aj-hit-image,使用{{product_link}}和{{image}}作为占位符,以便以后插入正确的值。
- aj-hit-title,使用{{_highlightResult.title.value}}--我还在{{variant_title}}中链接,为变体提供完整的标题。
- aj-hit-description,以呈现产品描述 - {{_highlightResult.body_html_safe.value}}。
- aj-hit-price 为{{价格}}。- 不要忘记添加你的货币(或者通过修改传递给模板的变量来添加)。
- aj-hit-stock,以显示我们有多少{{库存_数量}}的数量。
- aj-hit-link - 最后,产品页面的链接。{{产品_链接}}。
所有这些都被我的CSS文件很好地(IMHO)样式化了。样式设计不在本博文的范围内,请参考 buyzero.de 以获得一些灵感,然后编写你自己的代码。
更多关于{{_highlightResult.title.value}}的信息
使用三个大括号显示的变量将不会被Algolia for HTML转义。这里使用的是这种方法,以允许高亮显示。
Algolia将自动为你在标题等被匹配的部分周围加上标签。 _highlightResult 变量。你可以在输出中使用,向用户展示为什么认为该搜索结果与他们的搜索相关。
我稍后会告诉你如何修改传递给模板的值,因为你不希望渲染整个产品描述主体,例如。
aj_setup_search
var pb = aj_setup_search();
为了处理以后的搜索,我们从setup函数中返回一个变量(在setup_search函数中称为var point_both。 pb是它的缩写)。
var search = instantsearch({ appId: 'YOUR_APP_ID', apiKey: 'YOUR_API_KEY', // search only API key, no ADMIN key indexName: 'shopify_buyzero_de_products', urlSync: true, searchParameters: { hitsPerPage: 10 }, searchFunction(my_helper){ point_both.ihelper = my_helper; //search.helper.setQuery('Pi 3'); //sic! //my_helper.search(); //sic! if(my_helper.state.query === '') { return; } my_helper.search(); } //end searchFunction });//end instantsearch setup在这里,我们设置了搜索(如前所述,instantsearch已经包括在内,并通过另一个.js文件在页面上可用)。
你需要通过。
- 您的应用程序ID
- apiKey
- 索引名称
你将从你的Algolia后台获得这些信息。在那里你也可以浏览你的数据结构,看看你可以使用哪些参数来进行分面,比如说。
真正重要的部分是searchFunction(my_helper)函数。
该助手允许你通过你自己的脚本来驱动搜索,而不是从使用Algolia的instantsearch设置的搜索框小部件来触发搜索。
在这个特定的函数中,创建一个对这个帮助器的引用是很重要的。
point_both.ihelper = my_helper;
以后从搜索变量中访问帮助器,将 不是 工作。
事实上,你需要两者都有。看到这个例子的代码,我注释了吗?
//search.helper.setQuery('Pi 3'); //sic!
//my_helper.search(); //sic!
sic是拉丁语中的 "像这样"。意思是说,它确实必须以两种不同的方式访问,以设置查询,然后执行搜索。
另外,你 需要 在这里添加my_helper.search()。这将--我记得是--让你的部件正确地更新搜索......如果你发现你的结果没有更新,请检查你是否把它放在了这里
在添加部件后--我们将在下面讨论--我们用下面的代码结束搜索设置。
search.start()。
point_both.search = 搜索。
返回point_both。在这里,我们还添加了一个对搜索对象本身的引用,并将其返回给aj_setup函数。
注意point_both现在可以访问 "search "对象,以及我们从searchFunction函数中获得的特殊帮助对象 "ihelper"。
添加第一个小部件
我们将把结果作为第一个小组件加入。
search.addWidget(
instantsearch.widgets.hit({
容器:'#aj-search-results'。
模板。{
项目:document.getElementById('aj-hit-template').innerHTML。
空。"Es konnten leider keine Resultate für die Suchanfrage \"{{query}}" gefunden werden"。
},
transformData。{
item: function (my_result) {
//console.log(my_result)。
//console.log(my_result._highlightResult.body_html_safe.value)。
如果(my_result["variant_title"] == 'Default Title'){
my_result["variant_title"] = ";
}
否则
{
my_result["variant_title"] = ' :: ' + my_result["variant_title"]。
}
//my_result["body_html_safe"] = my_result["body_html_safe"].substring(0,175) + '...'。
//我们不想要多行,我们想要匹配字符串的真正结尾。/m将在行尾匹配。
var pattern_a = /(.*?)(]*)?$/i;
var pattern_b = /[^<]+$/i;
//取第一个匹配组--排除第二个匹配组。
var body_string = my_result._highlightResult.body_html_safe.value.substring(0,175).replace(pattern_a, "$1″)。
如果(pattern_b.test(body_string)){
body_string = body_string + ""
}
//寻找pi 3 b+
//产品ID https://buyzero.de/products/budget-kit-raspberry-pi-3-model-b?variant=698066665499
my_result._highlightResult.body_html_safe.value = body_string + '...' 。
my_result["product_link"] = "https://buyzero.de/products/” + my_result["handle"] + "?variant=" + my_result["id"] 。
返回my_result。
}
}
})
);放置输出的容器被选为'#aj-search-results',渲染结果的模板被选在这里: item: document.getElementById('aj-hit-template').innerHTML。
我假设他们把这个放在标签里,因为浏览器不会把内容作为HTML来呈现。
对于空的情况,我们只是把一个字符串作为模板传回来。
到目前为止真的很直接,对吗?
接下来我们用 转换数据 来准备你的产品的文本主体和其他变量的缩短版本,这些变量被传递到前面讨论的命中模板。
因为我们在搜索输出中引入了's - 使用Algolia的自动高亮功能 - 我们需要以一种安全的方式缩短文本。我已经为此准备了我自己的正则表达式,在我的示例代码中。
如果在缩短后有一个以),就会从输出中切掉。
如果有一个标签没有相应的标签来关闭它,我们就把它加进去。
产品链接的建立是为了获得手柄,并将id设置为变量。
添加分页
添加额外的小工具是很容易的。
// 在其他search.addWidget()的调用之后添加这个。
search.addWidget(
instantsearch.widgets.pagination({
容器:'#aj-search-pagination'。
render: function(my_obj){
console.log("render")。
console.log(my_obj)。
},
getConfiguration: function(my_obj){
console.log("getConfiguration")。
console.log(my_obj)。
}
})
);
你不想要控制台的日志输出......我是用这个来调试的,但显然忘了把它拿出来。对不起。我是人。
同样,该小组件的输出容器被设置。#aj-search-pagination'
你实际上不需要其他东西来使分页工作--设置小部件,并使其具有风格--你就可以了。
剖面图
通过分面,你的用户可以细化他们的搜索。
// Faceting
search.addWidget(
instantsearch.widgets.refinementList({
容器:'#aj-facet-brand'。
attributeName:'vendor',
操作符:'或'。
限度:5。
showMore: true,
cssClasses:{
header: 'aj-refine-header',
count:'aj-refine-count'
},
模板。{
标题:"Marke / Brand
}
})
);
- 你需要在你的Algolia后台查看可能的attributeNames - 它会显示你的数据的可用面(见下面的截图)。
- 5的限制不是指你的搜索结果,而是指Algolia为你的细化列表所显示的条目限制。
- 如果其他搜索参数发生变化,可用的细化内容将自动更新(例如,如果没有匹配的特定品牌,这个品牌将不会被显示出来)
- showMore: 将在小组件的底部显示一个显示更多的链接。
- 计。'aj-refine-count' - 你可以对你的搜索结果进行一些调整。可能比我在这里使用的要多 - 参考官方文件
清晰的面孔小组件
search.addWidget(
instantsearch.widgets.clearAll({
容器:'#aj-clear-all'。
模板。{
链接。'Filter zurücksetzen / Reset'(过滤)。
},
autoHideContainer: false,
clearsQuery: true。
})
);用这个来允许客户清除分面(即他们将再次显示与他们的查询相匹配的所有结果)。
除此以外不需要配置。
我不会谈论其他小工具--如果你有兴趣,可以看看我的代码。
绑定到搜索框
我们没有使用Algolia的搜索部件,而是绑定到我们的搜索表单输入上的一个按键事件,像这样。
var pb = aj_setup_search();
//#search_query是我们想要的输入。
$("#search_query").keyup(function(search) {
updateSearch(pb)。
});
}(刚才我们讨论了aj_setup_search,把它加在这里是为了告诉你pb的来历)。
我们这样做是为了在触发keyup事件时可以做额外的处理--隐藏我们之前在页面上显示的内容,并添加搜索结果,等等。
函数 updateSearch(pb){
var my_query = $("#search_query").val();
//$(".main-content").html(my_query)。
如果(my_query) {
$(".main-content").hide()。
$("#megamenu-header-menu2").hide()。
$("#ajr_na").显示()。
$("#sc-query").html(my_query)。
$("#aj-search-container").show()。
pb.search.helper.setQuery(my_query)。
//console.log(search_handle.helper.state)。
pb.ihelper.search()。
}
否则 {
$("#aj-search-container").hide()。
$(".main-content").show()。
$("#ajr_na").隐藏()。
$("#megamenu-header-menu2").show()。
}}
我们使用jQuery来获取搜索字段的值。如果它不是空的,我们就隐藏我们之前显示的主要内容,并显示搜索容器。
我们设置sc-query来向用户显示我们正在对他的条目作出回应。$("#sc-query").html(my_query)。
最后,重要的部分是这里的这些。
pb.search.helper.setQuery(my_query)。
pb.ihelper.search()。
如你所见。 我们需要使用两个不同的助手来设置查询和执行实际搜索.是的,需要这样做--幸运的是我发现有人在抱怨这种行为。
最后,如果搜索字符串是空的(用户按了Escape,或删除了它,或我们删除了它,或其他什么......),我们会隐藏搜索,并显示主要内容。
谢谢您的阅读
谢谢你的关注,我希望这能帮助那些想实现instantsearch.js而不使用Algolia的搜索小工具的人。
参考文献
谭家驹
Algolia
- Algolia instantsearch widgets 文档
- https://community.algolia.com/shopify/instant_search.html
- https://www.algolia.com/doc/tutorials/search-ui/instant-search/build-an-instant-search-results-page/instantsearchjs/
- https://www.algolia.com/doc/guides/searching/highlighting-snippeting
- https://www.algolia.com/doc/guides/search-ui/building-a-search-ui/
- https://community.algolia.com/instantsearch.js/v2/widgets/hits.html#struct-HitsTransforms
- https://stackoverflow.com/questions/42672838/algolia-instantsearch-add-a-callback-after-results-are-displayed
- https://community.algolia.com/algoliasearch-helper-js/gettingstarted.html
- https://github.com/algolia/instantsearch.js/issues/1924
- https://jsfiddle.net/bobylito/bsjdch4m/1/
- https://stackoverflow.com/questions/49638646/algolia-instantsearch-with-multiple-indices-and-multiple-pagination-widgets/49796164?noredirect=1#comment86826994_49796164
- https://github.com/algolia/instantsearch.js/issues/2887
奖金
- https://discourse.algolia.com/t/how-to-create-facet-widget-from-shopify-metafield/1710
- https://github.com/algolia/awesome-algolia