elasticsearch,Php,Html,elasticsearch" /> elasticsearch,Php,Html,elasticsearch" />

Php Elasticsearch将一个查询优先于另一个查询

Php Elasticsearch将一个查询优先于另一个查询,php,html,elasticsearch,Php,Html,elasticsearch,我有一个PHP脚本,它对Elasticsearch运行两个查询,并在PHP/HTML页面上回显结果。这两个查询在相同的字段中搜索相同的文本,但其中一个使用AND运算符,另一个使用OR运算符 我从AND运算符收到的结果是我希望首先显示的结果。OR运算符的结果也应出现,但应出现在第一个结果之后。现在的脚本似乎没有出现这种情况 剧本: <?php require_once 'vendor/autoload.php'; use Elasticsearch\ClientBuilder

我有一个PHP脚本,它对Elasticsearch运行两个查询,并在PHP/HTML页面上回显结果。这两个查询在相同的字段中搜索相同的文本,但其中一个使用AND运算符,另一个使用OR运算符

我从AND运算符收到的结果是我希望首先显示的结果。OR运算符的结果也应出现,但应出现在第一个结果之后。现在的脚本似乎没有出现这种情况

剧本:

<?php
    require_once 'vendor/autoload.php';
    use Elasticsearch\ClientBuilder;
    $client = ClientBuilder::create()->setHosts(['REDACTED:9200'])->build();
    $es = $client;

    if (isset($_GET['q'])) {
        $q = $_GET['q'];
        $query = $es->search([
            'index' => 'rss',
            'size' => '30',
            'body' => [
            'query' => [
                'simple_query_string' => [
                    'fields' => ["message","title"],
                    'query' => "$q",
                    'default_operator' => 'and',
                    'minimum_should_match' => '100%'
                ],
                'simple_query_string' => [
                    'fields' => ["message","title"],
                    'query' => "$q",
                    'default_operator' => 'or',
                    'minimum_should_match' => '80%'
                ]
            ]
            ]
        ]);
    }
    if($query['hits']['max_score'] >=1 ) {
        $results = $query['hits']['hits'];
    }

    ?>
   <!doctype html> 
    <html>
    <head>  
        <meta charset="utf-8">
        <title>Søkemotor</title>
        <link rel="stylesheet" href="css/main.css">
    </head>
    <body>
        <div class="img">
            <img src="img/DigRevLogo3.png" alt="Logo" width="200" height="50" class="img">
        </div>
        <div class="search">
            <form action="index.php" method="get" autocomplete="off" class="search_form">
                <label><input type="text" name="q" placeholder="Søk her"></label>
                <label><input type="submit" value="Søk" name="s"></label>
            </form>
        </div>

        <?php
        $noresult = "Ingen resultat på søket av $q.";
        $i = 0;
        if(isset($results)) {
            foreach($results as $r) { ?>
                <div class="result">
                    <div class="title">
                        <a href="<?php echo $r['_source']['link']; ?>"><?php echo $r['_source']['title'];?></a>
                    </div>

                    <div class="message">
                        <br>
                        <?php echo $r['_source']['message'];?>
                    </div>
                    <div class="published">
                        <br>
                        <?php echo $r['_source']['published'];?>            
                    </div>

                </div>
                <div class="noresult">
                <?php 
            }
        }
        else echo "<CENTER>$noresult</CENTER>"; ?>
                </div>
    </body>
    </html>
我想表现的是这样的:

RESULT 1: Apple Apple
RESULT 2: Apple Orange
RESULT 3: Apple Apple Apple
RESULT 4: Orange
RESULT 1: Apple Orange
RESULT 2: Apple Apple Apple
RESULT 3: Apple Apple
RESULT 4: Orange

我怎么能这样做?我正在使用安装在Debian 9上的Elasticsearch 6.3。PHP版本是7.2。如果有任何其他有用的信息,我会提供,但我不确定需要什么。

为了简化这一点,让我们将其简化为Elasticsearch查询,并将其切换到匹配,这通常是要开始的查询,然后根据需要深入:

DELETE fruit
PUT fruit
{
  "settings": {
    "number_of_shards": 1
  }
}
POST fruit/_doc
{
  "fruit": "Apple Apple"
}
POST fruit/_doc
{
  "fruit": "Apple Orange"
}
POST fruit/_doc
{
  "fruit": "Apple Apple Apple"
}
POST fruit/_doc
{
  "fruit": "Orange"
}
GET fruit/_search
{
  "query": {
    "match": {
      "fruit": "Apple Orange"
    }
  }
}
其结果是:

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 4,
    "max_score": 1.0498221,
    "hits": [
      {
        "_index": "fruit",
        "_type": "_doc",
        "_id": "oRg6HmUBs4EUCKS4dujJ",
        "_score": 1.0498221,
        "_source": {
          "fruit": "Apple Orange"
        }
      },
      {
        "_index": "fruit",
        "_type": "_doc",
        "_id": "oxg6HmUBs4EUCKS4d-hu",
        "_score": 0.87138504,
        "_source": {
          "fruit": "Orange"
        }
      },
      {
        "_index": "fruit",
        "_type": "_doc",
        "_id": "ohg6HmUBs4EUCKS4d-ga",
        "_score": 0.5062483,
        "_source": {
          "fruit": "Apple Apple Apple"
        }
      },
      {
        "_index": "fruit",
        "_type": "_doc",
        "_id": "oBg6HmUBs4EUCKS4duh-",
        "_score": 0.49042806,
        "_source": {
          "fruit": "Apple Apple"
        }
      }
    ]
  }
}
一般来说,分数是由BM25计算的(与旧的TF/IDF非常相似)。为什么我们要得到这个特定的订单

  • 第一个文档包含两个搜索词-这很有意义
  • 多次使用搜索词(苹果vs苹果)的文档排名更高
  • 为什么橙色的排名高于苹果?因为橙色在总体上更为罕见(在所有文档中出现两次,而苹果出现六次)
如果在查询中添加
explain
,它将实际显示所有分数的计算方式:

GET fruit/_search
{
  "explain": true, 
  "query": {
    "match": {
      "fruit": "Apple Orange"
    }
  }
}

如何更改默认行为?BM25中有一些参数可以调整。阅读,它描述了这里的许多概念。但请注意,这已经是一个相当高级的主题。

您是否试图在一个查询中同时获得两个搜索结果?@Ahmednuman是的,我想同时获得两个搜索结果,我只想第一次搜索的结果首先出现,因为它们同时包含两个单词(例如apple和orange)。若您使用的是数据库查询,则两个查询的联合将解决您的问题:
(带和条件的查询)联合(带或条件的查询)