Random_score выборка


(mishut) #1

Доброго времени суток.
Начал изучать эластик и столкнулся с проблемой.
Мне надо выбрать случайно 5 записей, но с условием, что определенное поле (type_id) в индексе этих записей должны быть разные. Если не получается найти 5 записей с таким условием, то находить столько, сколько получилось.

Спасите помогите пожалуйста ))

        $response = $this->client->search([
        'index' => 'addresses',
        'type' => 'address',
        'body' => [
            '_source' => ['id', 'type_id'],
            'size' => 5,
            'query' => [
                'bool' => [
                    'must' => array_merge(
                        [
                            ['function_score' => [
                                'random_score' => [
                                    'seed' => [session()->getId(), request()->path()],
                                ]
                            ],
                            ]
                        ],
                        [
                            ['term' => ['published' => '1']],
                        ],
                        array_filter([
                            $city ? ['term' => ['city_id' => $city->id]] : false,
                        ])
                    ),
                ],
            ],
        ],
    ]);

По сути есть вариант использовать aggs, но в таком случае невозможно (или я не умею) сделать random_score с использованием seed. Выборка впоследствии отображается на сайте в виде перелинковки и использование random_score позволяет сделать так, чтобы при обновлении странички выборка не изменялась.


(Igor Motov) #2

Возможно, только надо бакеты тоже случайно отсортировать. Пара способов приходит в голову:

PUT testidx
{
  "mappings": {
    "doc": {
      "properties": {
        "type_id": {
          "type": "keyword"
        }
      }
    }
  }
}

PUT testidx/doc/1
{
  "type_id": "A"
}

PUT testidx/doc/2
{
  "type_id": "A"
}

PUT testidx/doc/3
{
  "type_id": "A"
}

PUT testidx/doc/4
{
  "type_id": "B"
}

PUT testidx/doc/5
{
  "type_id": "B"
}

PUT testidx/doc/6
{
  "type_id": "C"
}

# By generating random bucket order
POST testidx/_search
{
  "query": {
    "function_score": {
      "random_score": {
        "seed": 123456789
      }
    }
  },
  "size": 0,
  "aggs": {
    "types": {
      "terms": {
        "field": "type_id",
        "size": 5,
        "script": {
          "source": "(_value + '1234567891').hashCode() + '_' + _value",
          "lang": "painless"
        },
        "order": {
          "_key": "asc"
        }
      },
      "aggs": {
        "hits": {
          "top_hits": {
            "size": 1
          }
        }
      }
    }
  }
}

# By using max record score
POST testidx/_search
{
  "query": {
    "function_score": {
      "random_score": {
        "seed": 123456789
      }
    }
  },
  "size": 0,
  "aggs": {
    "types": {
      "terms": {
        "field": "type_id",
        "size": 5,
        "order": {
          "max_score": "asc"
        }
      },
      "aggs": {
        "hits": {
          "top_hits": {
            "size": 1
          }
        },
        "max_score": {
          "max": {
            "script": "_score"
          }
        }
      }
    }
  }
}

(system) closed #3

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.