1

目前,我们在弹性搜索索引中有大量文档并进行全文搜索。我在项目中的下一个要求是查找文档中的所有信用卡数据。用户将来也可以动态定义一些正则表达式搜索规则。但使用标准分析器无法搜索信用卡信息或任何用户定义的规则。例如,假设一个文档包含信用卡信息,例如 4321-4321-4321-4321 或 4321 4321 4321 4321。弹性搜索将此数据索引为 4 个部分,如下所示:

  "tokens" : [
    {
      "token" : "4321",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "<NUM>",
      "position" : 0
    },
    {
      "token" : "4321",
      "start_offset" : 5,
      "end_offset" : 9,
      "type" : "<NUM>",
      "position" : 1
    },
    {
      "token" : "4321",
      "start_offset" : 10,
      "end_offset" : 14,
      "type" : "<NUM>",
      "position" : 2
    },
    {
      "token" : "4321",
      "start_offset" : 15,
      "end_offset" : 19,
      "type" : "<NUM>",
      "position" : 3
    }
  ]


我现在只是不考虑 Luhm 算法。如果我使用 reg exp "([0-9]{4}[- ]){3}[0-9]{4}" 进行基本正则表达式搜索以查找信用卡,则它不会返回任何内容,因为未分析数据并为此编制索引。我想为此目的,我需要为正则表达式搜索定义一个自定义分析器,并将另一个版本的数据存储在另一个字段或索引中。但正如我之前所说,将来用户将定义他/她自己的自定义规则模式进行搜索。我应该如何定义自定义分析器?我应该为此定义 ngram tokenizer(min:2, max:20) 吗?使用 ngram 标记器,我想我可以搜索所有已定义的正则表达式规则。但这合理吗?项目必须处理大量数据而没有任何性能问题。(将索引一个公司的整个文件系统)。对于此类数据发现问题,您还有其他建议吗?我目前的主要目的是寻找信用卡。感谢您的帮助。

4

1 回答 1

1

好的,这里有一对自定义分析器,可以帮助您检测信用卡号和社会保险号。随意调整您认为合适的正则表达式(通过添加/删除您将在数据中找到的其他字符分隔符)。

PUT test
{
  "settings": {
    "analysis": {
      "analyzer": {
        "card_analyzer": {
          "type": "custom",
          "tokenizer": "keyword",
          "filter": [
            "lowercase",
            "card_number"
          ]
        },
        "ssn_analyzer": {
          "type": "custom",
          "tokenizer": "keyword",
          "filter": [
            "lowercase",
            "social_number"
          ]
        }
      },
      "filter": {
        "card_number": {
          "type": "pattern_replace",
          "preserve_original": false,
          "pattern": """.*(\d{4})[\s\.\-]+(\d{4})[\s\.\-]+(\d{4})[\s\.\-]+(\d{4}).*""",
          "replacement": "$1$2$3$4"
        },
        "social_number": {
          "type": "pattern_replace",
          "preserve_original": false,
          "pattern": """.*(\d{3})[\s\.\-]+(\d{2})[\s\.\-]+(\d{4}).*""",
          "replacement": "$1$2$3"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "text": {
        "type": "text",
        "fields": {
          "card": {
            "type": "text",
            "analyzer": "card_analyzer"
          },
          "ssn": {
            "type": "text",
            "analyzer": "ssn_analyzer"
          }
        }
      }
    }
  }
}

让我们测试一下。

POST test/_analyze
{
  "analyzer": "card_analyzer",
  "text": "Mr XYZ whose SSN is 442-23-1452 has a credit card whose number was 3526 4728 4723 6374"
}

将产生一个不错的数字信用卡号:

{
  "tokens" : [
    {
      "token" : "3526472847236374",
      "start_offset" : 0,
      "end_offset" : 86,
      "type" : "word",
      "position" : 0
    }
  ]
}

同样对于 SSN:

POST test/_analyze
{
  "analyzer": "ssn_analyzer",
  "text": "Mr XYZ whose SSN is 442-23-1452 has a credit card whose number was 3526 4728 4723 6374"
}

将产生一个不错的纯数字社会安全号码:

{
  "tokens" : [
    {
      "token" : "442231452",
      "start_offset" : 0,
      "end_offset" : 86,
      "type" : "word",
      "position" : 0
    }
  ]
}

现在我们可以搜索信用卡或 SSN。假设我们有以下两个文件。SSN 和信用卡号相同,但它们使用不同的字符分隔符

POST test/_doc
{ "text": "Mr XYZ whose SSN is 442-23-1452 has a credit card whose number was 3526 4728 4723 6374" }

POST test/_doc
{ "text": "SSN is 442.23.1452 belongs to Mr. XYZ. He paid $20 via credit card number 3526-4728-4723-6374" }

您现在可以通过查找任何格式的信用卡号和/或 SSN 来找到这两个文件:

POST test/_search 
{
  "query": {
    "match": {
      "text.card": "3526 4728 4723 6374"
    }
  }
}

POST test/_search 
{
  "query": {
    "match": {
      "text.card": "3526 4728 4723-6374"
    }
  }
}

POST test/_search 
{
  "query": {
    "match": {
      "text.ssn": "442 23-1452"
    }
  }
}

上述所有查询都将匹配并返回两个文档。

于 2019-10-16T06:34:17.157 回答