Algolia和使用instantsearch.js从你的脚本中为Shopify服务

"好的艺术家会复制,伟大的艺术家会偷窃"。- 史蒂夫-乔布斯

灵感来自于 pimoroni.com 我想在我们的网店上实现一个类似的搜索。 buyzero.de buyzero.de目前是由Shopify提供的。

搜索在你输入时显示结果--在主页上,动态地取代先前显示的内容。非常酷,非常有用--而且非常、非常快(谢谢 Algolia!)

由于我对Algolia的现有文件感到困惑,而且他们的入职服务也不是很有帮助,所以我不得不自己想办法,并通过大量的谷歌搜索来解决这些问题。

这是我实施Algolia的经验总结。我是在一天之内完成的,单次编码时间约为12-14小时。

建议的准备工作:将开发代码注入你的页面中

我建议使用谷歌浏览器的扩展程序 谭家驹 用于在开发时从你的本地硬盘注入CSS和Javascript。

要做到这一点,你必须为Tampermonkey启用文件访问。打开。

chrome://extensions

单击 "详细信息",并将 "允许访问文件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}}。 &nbsp; <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

奖金