Алголия: как получить только первое вхождение поискового запроса в текстовом поле? - PullRequest
1 голос
/ 26 апреля 2020

Я использую Algolia для добавления поиска на мой сайт JAMStack. тем не менее, мой сайт имеет своего рода премиум-контент, и я хочу, чтобы он был доступен для поиска, оставаясь скрытым для пользователей.
Я могу достичь аналогичной функциональности, добавив атрибут body в поля поиска и удалив его из найденных атрибутов. , таким образом, Алголия будет по-прежнему искать в теле вхождения запроса, не раскрывая их пользователю.
Но более предпочтительным поведением для пользователя является возможность увидеть одно или два вхождения того, что он искал, в найденном body, но не может видеть весь текст премиум-контента.

Например, допустим, у нас есть следующие объекты в нашем индексе:

[
  {
    title: "Hello",
    body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
  },
  {
    title: "Hi",
    body: "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit"
  }
]

Теперь, если я запросю API algolia с текстом «i», ответ algolia выглядит следующим образом:

...
hits: [
  {
    title: "Hello",
    body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
    _highlightResults: {
      body: "Lorem <em>i</em>psum dolor s<em>i</em>t amet, consectetur ad<em>i</em>p<em>i</em>sc<em>i</em>ng el<em>i</em>t, sed do e<em>i</em>usmod tempor <em>i</em>nc<em>i</em>d<em>i</em>dunt ut labore et dolore magna al<em>i</em>qua. Ut en<em>i</em>m ad m<em>i</em>n<em>i</em>m ven<em>i</em>am, qu<em>i</em>s nostrud exerc<em>i</em>tat<em>i</em>on ullamco labor<em>i</em>s n<em>i</em>s<em>i</em> ut al<em>i</em>qu<em>i</em>p ex ea commodo consequat. Du<em>i</em>s aute <em>i</em>rure dolor <em>i</em>n reprehender<em>i</em>t <em>i</em>n voluptate vel<em>i</em>t esse c<em>i</em>llum dolore eu fug<em>i</em>at nulla par<em>i</em>atur. Excepteur s<em>i</em>nt occaecat cup<em>i</em>datat non pro<em>i</em>dent, sunt <em>i</em>n culpa qu<em>i</em> off<em>i</em>c<em>i</em>a deserunt moll<em>i</em>t an<em>i</em>m <em>i</em>d est laborum."
    }
  },
  {
    title: "Hi",
    body: "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit",
    _highlightResults: {
      body: "Sed ut persp<em>i</em>c<em>i</em>at<em>i</em>s unde omn<em>i</em>s <em>i</em>ste natus error s<em>i</em>t voluptatem accusant<em>i</em>um doloremque laudant<em>i</em>um, totam rem aper<em>i</em>am, eaque <em>i</em>psa quae ab <em>i</em>llo <em>i</em>nventore ver<em>i</em>tat<em>i</em>s et quas<em>i</em> arch<em>i</em>tecto beatae v<em>i</em>tae d<em>i</em>cta sunt expl<em>i</em>cabo. Nemo en<em>i</em>m <em>i</em>psam voluptatem qu<em>i</em>a voluptas s<em>i</em>t aspernatur aut od<em>i</em>t aut fug<em>i</em>t, sed qu<em>i</em>a consequuntur magn<em>i</em> dolores eos qu<em>i</em> rat<em>i</em>one voluptatem sequ<em>i</em> nesc<em>i</em>unt. Neque porro qu<em>i</em>squam est, qu<em>i</em> dolorem <em>i</em>psum qu<em>i</em>a dolor s<em>i</em>t amet, consectetur, ad<em>i</em>p<em>i</em>sc<em>i</em> vel<em>i</em>t"
  }
]

Но я хочу, чтобы он возвращал следующее:

[
  {
    title: "Hello",
    _highlightResults: {
      body: "Lorem <em>i</em>psum dolor sit amet" // only the first occurance with some context
    }
  },
  {
    title: "Hi",
    _highlightResults: {
      body: "Sed ut persp<em>i</em>ciatis unde" // only the first occurance with some context
    }

  }
]

Я знаю нечто похожее на это это можно сделать с помощью фрагментов, но если вы обратите особое внимание, поле тела также удаляется из самого тела попадания, поэтому полное тело никогда не отправляется клиенту. Клиент может осуществлять поиск по премиум-контенту, в то время как сам контент остается неэкспонированным.

Как этого добиться с помощью API Algolia?

1 Ответ

1 голос
/ 27 апреля 2020

Вы должны иметь возможность реализовать такую ​​логику c с помощью сниппета . Вам не нужно возвращать поле для его поиска. Функция сниппета может контролировать, сколько контекста отправляется обратно с совпадением. Вы можете установить ограничение для возврата только нескольких слов, чтобы ограничить совпадение одним вхождением. Хотя точность не будет 100%, два совпадения могут быть возвращены, если они ближе указанного предела (что не должно быть проблемой для реального случая использования).

В приведенном ниже примере возвращается только name атрибут для поиска. description устанавливается в searchableAttributes. Это означает, что запрос будет использовать этот атрибут для поиска. Это также означает, что мы можем использовать его с функцией сниппета. Здесь фрагмент ограничен 10 словами.

index.search('apple', {
  attributesToRetrieve: ['name'],
  attributesToSnippet: ['description:10'],
});

Обратите внимание, что эти значения устанавливаются во время поиска. Для реализации на стороне клиента это означает, что пользователь сможет изменять эти значения. В вашем случае используется контент премиум-класса, поэтому проблематично c. Чтобы обойти эту проблему, вы должны использовать API Key с записанными в нем параметрами. Вы не сможете переопределить их во время поиска.

...