解析高级搜索条件的单个用户输入字符串

时间:2017-01-17 07:35:11

标签: javascript regex node.js pattern-matching xregexp

我正在为我正在编写的博客开发自定义搜索功能。这个博客面向技术倾向的读者,我想让读者通过在搜索字段中定义一些高级搜索条件来搜索文章(而不是有多个搜索输入,一个用于 title ,一个用于标签,一个用于类别等等)。与Jiras advanced search或Googles search operators有些相似。

我将使用Javascript对此进行编码,但我会使用 xRegExp 库,它支持本机RegExp不具备的所有酷功能(命名组匹配,展望未来,请看背后等)

可搜索的“字段”将是:

  • 标题
  • 摘要
  • 作者
  • 分类
  • 标签
  • 已创建(日期)
  • 更新(日期)
  • (未指定字段)常规搜索词组

要将搜索“字段”添加到搜索条件,您只需键入上面的字段名称之一,然后输入冒号(:),然后输入与之关联的搜索短语那个领域。

除此之外,我还希望观众能够在搜索条件中添加一些“ OR ”和“ AND ”逻辑,例如搜索文章与作者 john.doe OR mike.smith ,或者带有标签 bash AND <的文章/ strong> 脚本 OR 运算符可以是|| AND 运算符可以是&&

一些示例搜索字符串:

  

作者 linus 标记 linux Linux如何开始

  • 作者 Linus
  • 标记 Linux
  • 一般搜索词: Linux如何开始
  

作者 john.doe || jane.smith 类别 infosec || linux 标记 linux &amp;&amp; 安全性 保护您的第一台Linux服务器

  • 作者 john.doe jane.smith
  • 类别 Infosec Linux
  • 标记 Linux 安全
  • 常规搜索词组:保护您的第一台Linux服务器

问题

我希望尽可能多地通过Regex完成字符串解析。我在regex101上发生了一些事情,但我遇到了多次匹配模式的问题,用空格分隔..所以任何帮助都会受到赞赏。谢谢!

1 个答案:

答案 0 :(得分:1)

PS。对不起,我没有使用你的lib。如果我真的需要,我只会回到libs。没有充分阅读你的信息。除此之外,我认为代码可读/易于编辑(与大多数正则表达式不同)。

我也看到了nodejs标签,如果您使用它来“发送”,您可以轻松地将对转换为键/值,如下所示:

const pairSeperator = ':';
const valueSeperators = [
  { splitter: '||', replacingValue: 'OR' },
  { splitter: '&&', replacingValue: 'AND' },
];

const validKeyNames = [
  'title',
  'summary',
  'author',
  'category',
  'tag',
  'created',
  'updated',
];

function isValidKeyValuePair(input) {
  const possiblePair = input.split(pairSeperator);

  if (possiblePair.length == 2) {
    return validKeyNames.indexOf(possiblePair[0]) > -1;
  }

  return false;
}

function parseValue(value) {
  const valueSeperator = valueSeperators.find((s) => value.indexOf(s.splitter) > -1);
  if (valueSeperator) {
    return value
      .split(valueSeperator.splitter)
      .join(` ${valueSeperator.replacingValue} `);
  }

  return value;
}

function pairReduce(memo, strPair) {
  const [key, value] = strPair.split(pairSeperator);

  obj[key] = parseValue(value);
  return obj;
}


// this is function which handles your searchTerm
function parseSearch(searchTerm) {
  const splittedSearchTerm = searchTerm.split(' ');

  const filters = splittedSearchTerm
    .filter(isValidKeyValuePair)
    .reduce(pairReduce, {});

  const searchTerm = splittedSearchTerm
    .filter(input => !isKeyValuePair(input))
    .join(' ');

  return Object.assign(filters, { searchTerm });
  // input: parseSearch("tag:linux why Linux rocks?");
  // output: { "tag": "linux", "searchTerm": "why Linux rocks?" }
}