【问题标题】:Use Algolia Docsearch index for Instantsearch.js section in Docusaurus page在 Docusaurus 页面中为 Instantsearch.js 部分使用 Algolia Docsearch 索引
【发布时间】:2019-03-04 19:15:21
【问题描述】:

我有一个使用 Docusaurus.io 构建的文档站点,并且正在使用 Docsearch 作为我在导航栏中的搜索 - 这工作正常。但是,我也想在网站的登录页面上实现 Algolia 即时搜索。该代码在使用 Instantsearch 设置的旧索引上运行良好,但是当我将新 Docsearch 索引的 API 密钥和 ID 插入到 Instantsearch 配置函数中时,我得到了一个我无法理解的 JSON 对象流.

这是我正在尝试使用的模板(它适用于 Jekyll 网站上的旧索引):

const hitTemplate = function(hit) {
    console.log(hit);
  let url = hit.url;
  const title = hit.lvl1;
  const content = hit._highlightResult.matchedWords;

  return `
    <div class="post-item">
      <a class="post-link" href="${url}">
        <h4>${title}</h4>
      </a>
      <div class="search-article-description">${content}</div>
      <a href="${url}" class="read-more">Read More &raquo;</a>
    </div>
  `;

这会导致&lt;div&gt; 出现空白。

当没有应用模板时,我的结果以嵌套 JSON 对象的形式返回。

我试图实现的是一个额外的即时搜索,它只出现在文档网站的主页上。据我了解,我在 Docsearch 中不能有两个输入选择器,这就是我一直尝试使用 Instantsearch 的原因。我需要一个适用于 Docsearch API 返回数据方式的模板。

【问题讨论】:

    标签: algolia instantsearch.js instantsearch docusaurus


    【解决方案1】:

    经过一周的反复试验和 Docsearch 开发人员通过 github 提供的一些非常有价值的帮助,我想出了一个适用于我的文档站点的解决方案,并在此分享它,希望其他沮丧的 Docusaurus 用户, Docsearch 和 Instantsearch 找到了解决方案:

    instantsearch.js(在网站/静态/js中找到):

    // instantSearch on homepage
    document.addEventListener('DOMContentLoaded', () => {
      // Set initial parameters for instantsearch on the homepage
      const mainSearch = instantsearch({
        appId: '...',
        apiKey: '...',
        indexName: 'your-docsearch-index-name',
        searchParameters: {
          hitsPerPage: 10
        },
        routing: true
      });
    
      mainSearch.addWidget(
        instantsearch.widgets.configure({
          filters: 'version:1.5.5' // set latest version here
        })
      );
    
      // initialize SearchBox
      mainSearch.addWidget(
        instantsearch.widgets.searchBox({
          container: '#search_input_main',
          placeholder: 'Search the Docs',
          autofocus: false,
          poweredBy: true
        })
      );
      // add hits cont
      mainSearch.addWidget(
        instantsearch.widgets.hits({
          container: '#search-hits',
          templates: {
            empty: 'No results for the search term <em>"{{query}}"</em>.',
            item: $('#results-template').html() // this is the template at index.js
          },
          hitsPerPage: 10
        })
      );
    
      // add pagination
      mainSearch.addWidget(
        instantsearch.widgets.pagination({
          container: '#pagination-container',
          maxPages: 20,
          // default is to scroll to 'body', here we disable this behavior
          scrollTo: '#search-container'
        })
      );
    
      mainSearch.start();
    
      // Toggle search results
      const search_input_main = document.querySelector('#search_input_main');
      const searchContainer = document.querySelector('#search-container');
    
      // Bind keyup event on the input
      search_input_main.addEventListener('keyup', function() {
        if (search_input_main.value.length > 0) {
          searchContainer.classList.remove('hidden');
        } else {
          searchContainer.classList.add('hidden');
        }
      });
    
      // hide results on reset
      document.querySelector('.ais-search-box--reset').addEventListener('click', function() {
        searchContainer.classList.add('hidden');
      });
    
    });
    

    这是我的页面/en/index.js:

    const React = require('react');
    ...
    // for homepage instantsearch
    let resultsTemplate = `
    <script type="text/template" id="results-template">
      <div class="ais-result">
        {{#hierarchy.lvl0}}
        <div class="ais-lvl0">
          <a title="{{_highlightResult.hierarchy.lvl1.value}}" href="{{{url}}}"><h4>{{{_highlightResult.hierarchy.lvl0.value}}}</h4></a>
        </div>
        {{/hierarchy.lvl0}}
    
        <div class="ais-lvl1 breadcrumbs">
          {{#hierarchy.lvl1}} {{{_highlightResult.hierarchy.lvl1.value}}} {{/hierarchy.lvl1}} {{#hierarchy.lvl2}} > {{{_highlightResult.hierarchy.lvl2.value}}} {{/hierarchy.lvl2}} {{#hierarchy.lvl3}} > {{{_highlightResult.hierarchy.lvl3.value}}} {{/hierarchy.lvl3}}
          {{#hierarchy.lvl4}} > {{{_highlightResult.hierarchy.lvl4.value}}} {{/hierarchy.lvl4}}
        </div>
    
        <div class="ais-content">
          {{{#content}}} {{{_highlightResult.content.value}}} {{{/content}}}
        </div>
      </div>
    </script>
    `
    ...
    
    const SearchInput = () => (
      <div>
        <div className='productShowcaseSection small-paddingBottom paddingTop' style={{textAlign: 'center'}}>
          <h3>Get the most out of Stackery's serverless toolkit</h3>
          <Container>
            <div className='search_input_div'>
              <input id="search_input_main" type="text" className="form-control" placeholder="Search the docs" aria-label="Search" aria-describedby="search"></input>
            </div>
          </Container>
        </div>
      </div>
    );
    
    const SearchHits = () => {
      return (
        <Container className='hidden' id='search-container'>
          <h3>Search results:</h3>
          <div id='search-hits'></div>
          <div id='pagination-container'></div>
          <div
            dangerouslySetInnerHTML={{ __html: resultsTemplate }}
          />
        </Container>
      )
    }
    
    class HomeSplash extends React.Component {
      render () {
        const language = this.props.language || '';
        return (
          <SplashContainer>
            <div className='inner'>
              <ProjectTitle />
              <PromoSection>
                ...
              </PromoSection>
              <SearchInput />
            </div>
          </SplashContainer>
        );
      }
    }
    ...
    
    class Index extends React.Component {
      render () {
        const language = this.props.language || '';
    
        return (
          <div>
            <HomeSplash language={language} />
            <SearchHits />
            <BrowseDocs />
            <TryIt />
          </div>
        );
      }
    }
    
    module.exports = Index;
    

    注意事项:

    • 请务必添加 filters: 'version:your-version',否则即时搜索将返回您拥有的每个版本的结果,从而导致大量重复。
    • instantsearch.js 底部的 JQuery 用于根据搜索输入中的 keyup 事件显示和隐藏搜索结果出现的 &lt;div&gt;
    • 我使用const mainSearch = instantsearch({... 而不是const search 的原因是默认导航栏Docsearch 已经使用了search 变量。如果您在页面上有多个搜索,则需要执行此操作。
    • 虽然本指南是特定于 Docusaurus 的,但这个有用的 JSfiddle 展示了如何在普通静态站点上使用 Docsearch 索引实现即时搜索:https://jsfiddle.net/s_pace/965a4w3o/1/
    • 如果您需要帮助在自己的 Docusaurus 网站上实现此功能,请发表评论,我很乐意为您提供帮助

    【讨论】:

      猜你喜欢
      • 2017-11-29
      • 2021-06-10
      • 2016-05-27
      • 2017-01-03
      • 2018-04-04
      • 2016-04-02
      • 2022-01-03
      • 2016-08-07
      • 1970-01-01
      相关资源
      最近更新 更多