Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在php中搜索大量文本_Php_Mysql_Symfony_<img Src="//i.stack.imgur.com/RUiNP.png" Height="16" Width="18" Alt="" Class="sponsor Tag Img">elasticsearch - Fatal编程技术网 elasticsearch,Php,Mysql,Symfony,elasticsearch" /> elasticsearch,Php,Mysql,Symfony,elasticsearch" />

在php中搜索大量文本

在php中搜索大量文本,php,mysql,symfony,elasticsearch,Php,Mysql,Symfony,elasticsearch,我有一个基于Symfony2的项目,它允许用户创建一系列规则,将项目分配到不同的类别。它是一个后端项目,因此只有少数用户访问它 规则基于短语,项目是文本对象。我正试图找出一种最好的方法来搜索这些文本对象,并尽可能快速、顺利地将规则应用于这些文本对象 例如,如果用户创建了5条规则(短语:篮球,足球,棒球,游泳,跑步),则所有匹配这些短语的文本对象都应分配给运动类别,我想我可以使用ElasticSearch快速返回这些对象的ID,然后使用简单的插入或更新mysql查询保存分配 我担心性能,例如,如果

我有一个基于Symfony2的项目,它允许用户创建一系列规则,将项目分配到不同的类别。它是一个后端项目,因此只有少数用户访问它

规则基于短语,项目是文本对象。我正试图找出一种最好的方法来搜索这些文本对象,并尽可能快速、顺利地将规则应用于这些文本对象

例如,如果用户创建了5条规则(短语:
篮球
足球
棒球
游泳
跑步
),则所有匹配这些短语的文本对象都应分配给运动类别,我想我可以使用ElasticSearch快速返回这些对象的ID,然后使用简单的插入或更新mysql查询保存分配

我担心性能,例如,如果索引中有一百万个文本对象,比如说,有50k个对象与这些规则匹配,部分运行搜索查询,例如将每个ElasticSearch查询的范围限制为50k(迭代整个索引),那么,将数据更新/插入MySQL将是一种可接受的方法

因此,运行查询(伪):

等等

ElasticSearch是这种处理的好选择吗?或者我应该坚持使用MySQL并使用regexp运行查询(当然是分块)

也许我可以检查一下现有的解决方案?不幸的是,我仅限于PHP和Symfony2,但如果有任何更好的解决方案值得检查,我可能能够向客户推荐


希望有人能帮助我,欢迎任何帮助。

如果您使用的是
文本
字段,您可以在表上创建
全文
索引:

CREATE TABLE texts(
    id int not null auto_increment primary key,
    text_field1 text,
    text_field2 text,
    text_field3 text
)Engine = MyISAM;  -- InnoDB supports fulltext indexes since v5.6

CREATE FULLTEXT INDEX itexts on texts(text_field1,text_field2,text_field3);
然后可以使用全文表达式进行搜索(至少查找一个术语):

或者找到所有术语

SELECT * FROM texts 
WHERE MATCH (text_field1,text_field2,text_field3) 
AGAINST ('+basketball +baseball +football');
现在,在您的项目中,您可以将规则转换为全文搜索表达式,并使用常规symfony查询执行它

有关全文搜索的详细信息:
这绝对是Elasticsearch擅长的。例如,我的笔记本电脑上有一个索引(Macbook Air,所以没什么比这更强大),其中有4095005个代表不同名称的文档

使用过滤器 您请求的用例基本上只是精确的匹配过滤。为此,我们可以使用Elasticsearch过滤器,其速度非常快。下面是一个示例筛选器,用于查找五个不同的名称:

curl -XGET "http://localhost:9200/test_names/_search" -d'
{
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "should": [
            {
              "term": {
                "first_name": "miguel"
              }
            },
            {
              "term": {
                "first_name": "ella"
              }
            },
            {
              "term": {
                "first_name": "almeta"
              }
            },
            {
              "term": {
                "first_name": "garret"
              }
            },
            {
              "term": {
                "first_name": "simon"
              }
            }
          ]
        }
      }
    } 

  }
}'
以及响应的顶部部分:

{
 "took": 85,
 "timed_out": false,
 "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
 },
 "hits": {
    "total": 3755,
    "max_score": 1,
 ....
take:85
意味着过滤400万个文档并找到匹配的3755需要85毫秒。如果我再次运行相同的筛选器,我会得到:

{
 "took": 4,
 "timed_out": false,
 "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
 },
 "hits": {
    "total": 3755,
    "max_score": 1,
 ....
现在执行时间仅为4ms。这是因为Elasticsearch缓存过滤器位集,因此后续对“miguel”、“ella”、“almeta”、“garret”或“simon”的搜索将以极快的速度执行(直到这些值从缓存中逐出)

使用查询 查询提供了更健壮的全文搜索,并将根据文档匹配程度对文档进行排序。所以你可以这样做:

curl -XGET "http://localhost:9200/test_names/_search" -d'
{
  "query" : {
    "match": {
      "first_name": "miguel ella almeta garret simon"
    }
  }
}'
这基本上等同于“米格尔、埃拉、阿尔梅塔、加勒特或西蒙”,但经过加权后,匹配更多术语的文档得分更高。它在54毫秒内执行(再次在我的笔记本电脑上搜索400万个文档):


这只是Elasticsearch所能做的皮毛而已。但是我可以肯定地说,它可以提供您所描述的功能,而且速度非常非常快。

谢谢您的回答,伊万,我熟悉MySQL中的全文,虽然我不知道InnoDB表已经支持它,但需要检查文档。谢谢还有,在使用全文搜索时,有没有办法判断哪个短语是匹配的?例如,我搜索至少与一个短语匹配的项目:篮球、足球、棒球。MySQL返回100条记录,有没有办法告诉每个返回的记录哪个短语匹配?您可以添加表达式:
MATCH(text\u field1,text\u field2,text\u field3)对(“+basketball+basketball+football”)
作为列名,并按该列排序以获得匹配率高的记录。谢谢Ivan,但这并不是我所需要的,它给了我分数,而不是匹配每条记录的短语。我在玩全文游戏时遇到的另一个问题是特殊字符的处理,例如,当试图查找包含URL部分的记录时:“nba.com/players”,它返回匹配nba、com或players的记录。有什么办法可以解决这个问题吗?
{
 "took": 4,
 "timed_out": false,
 "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
 },
 "hits": {
    "total": 3755,
    "max_score": 1,
 ....
curl -XGET "http://localhost:9200/test_names/_search" -d'
{
  "query" : {
    "match": {
      "first_name": "miguel ella almeta garret simon"
    }
  }
}'
{
   "took": 54,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 3755,
      "max_score": 0.8923058,
    ...