简体   繁体   English

Javascript/React 中的搜索功能

[英]Search functionality in Javascript/React

I have to implement a search functionality in an app I am currently working on.我必须在我目前正在开发的应用程序中实现搜索功能。 However, the problem is how we display the results.然而,问题是我们如何显示结果。 For Example,例如,

const queries = ['revised sales report','sales report',  'revision: sales investors report']

function filterResults(term) {
  const search = queries.filter(item =>item.toLowerCase().includes(term.toLowerCase()));
  return search;
  }

  console.log(filterResults('sales report'))

The above function gives me上面的函数给了我

[
"revised sales report",
"sales report"
]

as results.作为结果。 But however, the desired output should be,但是,所需的输出应该是,

[
"sales report",
"revised sales report",
"revision: sales investors report"
]

That is, my first result should always start with the exact search string ie, even though sales report is the second item in the array, that is the exact match so it should appear first, second result can contain string at any place, ie, the first item in the array has the search term but it starts with some other word and hence it should appear second.也就是说,我的第一个结果应该始终以精确的搜索字符串开头,即,即使销售报告是数组中的第二个项目,也就是精确匹配,因此它应该首先出现,第二个结果可以在任何位置包含字符串,即,数组中的第一项具有搜索词,但它以其他单词开头,因此它应该出现在第二位。 and subsequent result can have each input in different places of the sentence , ie, the third item in the array has both the term sales and report but it is in disconnected and appears in different part of the sentence so it should appear after the second result.并且随后的结果可以在句子的不同位置具有每个输入,即,数组中的第三项同时具有术语销售和报告,但它处于断开状态并出现在句子的不同部分,因此它应该出现在第二个结果之后. But the function I made above completely ignores the third result.但是我上面做的函数完全忽略了第三个结果。

I have no clue how to approach this.我不知道如何处理这个问题。 I just started working 3 months ago.我刚开始工作 3 个月前。 Any pointers on how to approach would be helpful.有关如何处理的任何指示都会有所帮助。

Assuming your actual search string was 'sales report' and your intention was to return假设您的实际搜索字符串是'sales report'并且您打算返回

  • exact match (hereafter case-insensitively) as a first search output精确匹配(以下不区分大小写)作为第一个搜索输出
  • partial match (where searched string is a substring of some query item)部分匹配(其中搜索字符串是某个query项的子字符串)
  • vague match (where both 'sales' and 'report' strings are present in arbitrary order模糊匹配(其中'sales''report'字符串以任意顺序出现

You may do the following:您可以执行以下操作:

 const queries = ['revised sales report','sales report', 'revision: sales investors report'], searchedString = 'sales report', search = (arr, str) => { const exactMatch = arr.find(s => s.toLowerCase() == str.toLowerCase()), partialMatches = arr.filter(s => s.toLowerCase().includes(str.toLowerCase())), vagueMatches = arr.filter(s => str .toLowerCase() .split(' ') .every(w => s.toLowerCase().includes(w)) ) return [...new Set([exactMatch, ...partialMatches, ...vagueMatches])] } console.log(search(queries, searchedString))

ps this, of course, does not take punctuation into account (but may be adjusted to do that either), but surely gives an idea on how to approach your problem. ps,当然,这并没有考虑标点符号(但也可以调整为这样做),但肯定会提供有关如何解决您的问题的想法。

From your description you seem to want to rank results based on 3 different criteria根据您的描述,您似乎想根据 3 个不同的标准对结果进行排名

  1. result === query结果 === 查询
  2. result includes query结果包括查询
  3. results includes all words of query结果包括所有查询词

So you search function, will have to search for each type of match, and assign a rank to the result.因此,您的搜索功能必须搜索每种类型的匹配项,并为结果分配一个排名。

A naive approach天真的方法

 const queries = ['revised sales report', 'sales report', 'revision: sales investors report'] const matchWholeString = (value, term) => value === term; const matchIncludesString = (value, term) => value.includes(term); const matchIncludesAllWords = (value, term) => term.split(/\\s+/).every(word => value.includes(word)); function filterResults(term) { const lowercaseTerm = term.toLowerCase(); const search = queries.map(query => { const lowercaseQuery = query.toLowerCase(); if (matchWholeString(lowercaseQuery, lowercaseTerm)) { return { query, rank: 1000 }; } if (matchIncludesString(lowercaseQuery, lowercaseTerm)) { return { query, rank: 100 } } if (matchIncludesAllWords(lowercaseQuery, lowercaseTerm)) { return { query, rank: 10 } } return { query, rank: 0 } }).filter(({ rank }) => rank).sort((a, b) => a.rank < b.rank).map(({ query }) => query); return search; } console.log(filterResults('sales report'))

This is how the includes function works.这就是includes函数的工作原理。 it simply checks whether the value you provided which is 'sales report' let's say, exist in the string you are checking against which it does in the first two strings in the list, but not in the last one.它只是检查您提供的'sales report'值是否存在于您正在检查的字符串中,它在列表中的前两个字符串中是否存在,但在最后一个字符串中不存在。 includes checks the exact value, it won't do a fuzzy search for you.包括检查确切的值,它不会为您进行模糊搜索。

You can use something like https://fusejs.io/ to achieve what you want.你可以使用类似https://fusejs.io/ 的东西来实现你想要的。 It can do a fuzzy search and will provide you with a score for each found value so you can use that to order the results in the way you described.它可以进行模糊搜索,并为您提供每个找到的值的分数,以便您可以使用它按照您描述的方式对结果进行排序。

an example from their documentation他们文档中的一个例子

const list = ["Old Man's War", 'The Lock Artist']
const options = {
  includeScore: true
}

const fuse = new Fuse(list, options)

const result = fuse.search('od man')

result结果

[
  {
    "item": "Old Man's War",
    "refIndex": 0,
    "score": 0.35
  }
]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM