Version
directorytree/opensearch-scout-driver: v1.1.0
Description
SearchRequestPayload::makeFilter() builds each terms filter directly from
$builder->whereIns values without reindexing them:
foreach ($builder->whereIns as $field => $values) {
$filter[] = ['terms' => [$field => $values]];
}
When a values array has non-sequential integer keys, json_encode() serializes it as a
JSON object instead of an array. OpenSearch then reads the object form under terms
as a terms lookup and rejects the request.
This happens with ordinary input — e.g. a values array left keyed by array_unique()
(which preserves keys) or a keyed pluck().
To reproduce
$values = array_unique(['active', 'active', 'invited']); // [0 => 'active', 2 => 'invited']
Model::search('foo')->whereIn('status', $values)->get();
The generated filter becomes:
{ "terms": { "status": { "0": "active", "2": "invited" } } }
Expected
{ "terms": { "status": ["active", "invited"] } }
Actual
OpenSearch returns HTTP 400:
x_content_parse_exception: [1:2039] [terms_lookup] unknown field [1]
Suggested fix
Reindex the values in makeFilter() so a terms filter always serializes as a JSON
array (whereIn means "field is one of this list", so the value is never meant to be an
object / terms lookup):
$filter[] = ['terms' => [$field => array_values($values)]];
Version
directorytree/opensearch-scout-driver: v1.1.0Description
SearchRequestPayload::makeFilter()builds eachtermsfilter directly from$builder->whereInsvalues without reindexing them:When a values array has non-sequential integer keys,
json_encode()serializes it as aJSON object instead of an array. OpenSearch then reads the object form under
termsas a terms lookup and rejects the request.
This happens with ordinary input — e.g. a values array left keyed by
array_unique()(which preserves keys) or a keyed
pluck().To reproduce
The generated filter becomes:
{ "terms": { "status": { "0": "active", "2": "invited" } } }Expected
{ "terms": { "status": ["active", "invited"] } }Actual
OpenSearch returns HTTP 400:
Suggested fix
Reindex the values in
makeFilter()so atermsfilter always serializes as a JSONarray (
whereInmeans "field is one of this list", so the value is never meant to be anobject / terms lookup):