You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
4.5 KiB
161 lines
4.5 KiB
[[php_json_objects]]
|
|
== Dealing with JSON Arrays and Objects in PHP
|
|
|
|
A common source of confusion with the client revolves around JSON arrays and objects, and how to specify them in PHP.
|
|
In particular, problems are caused by empty objects and arrays of objects. This page will show you some common patterns
|
|
used in Elasticsearch JSON API, and how to convert that to a PHP representation.
|
|
|
|
=== Empty Objects
|
|
|
|
The Elasticsearch API uses empty JSON objects in several locations, and this can cause problems for PHP. Unlike other
|
|
languages, PHP does not have a "short" notation for empty objects and so many developers are unaware how to specify
|
|
an empty object.
|
|
|
|
Consider adding a Highlight to a query:
|
|
|
|
[source,json]
|
|
----
|
|
{
|
|
"query" : {
|
|
"match" : {
|
|
"content" : "quick brown fox"
|
|
}
|
|
},
|
|
"highlight" : {
|
|
"fields" : {
|
|
"content" : {} <1>
|
|
}
|
|
}
|
|
}
|
|
----
|
|
<1> This empty JSON object is what causes problems.
|
|
|
|
The problem is that PHP will automatically convert `"content" : {}` into `"content" : []`, which is no longer valid
|
|
Elasticsearch DSL. We need to tell PHP that the empty object is explicitly an object, not an array. To define this
|
|
query in PHP, you would do:
|
|
|
|
[source,json]
|
|
----
|
|
$params['body'] = array(
|
|
'query' => array(
|
|
'match' => array(
|
|
'content' => 'quick brown fox'
|
|
)
|
|
),
|
|
'highlight' => array(
|
|
'fields' => array(
|
|
'content' => new \stdClass() <1>
|
|
)
|
|
)
|
|
);
|
|
$results = $client->search($params);
|
|
----
|
|
<1> We use the generic PHP stdClass object to represent an empty object. The JSON will now encode correctly.
|
|
|
|
By using an explicit stdClass object, we can force the `json_encode` parser to correctly output an empty object, instead
|
|
of an empty array. Sadly, this verbose solution is the only way to acomplish the goal in PHP...there is no "short"
|
|
version of an empty object.
|
|
|
|
=== Arrays of Objects
|
|
|
|
Another common pattern in Elasticsearch DSL is an array of objects. For example, consider adding a sort to your query:
|
|
|
|
[source,json]
|
|
----
|
|
{
|
|
"query" : {
|
|
"match" : { "content" : "quick brown fox" }
|
|
},
|
|
"sort" : [ <1>
|
|
{"time" : {"order" : "desc"}},
|
|
{"popularity" : {"order" : "desc"}}
|
|
]
|
|
}
|
|
----
|
|
<1> "sort" contains an array of JSON objects
|
|
|
|
This arrangement is *very* common, but the construction in PHP can be tricky since it requires nesting arrays. The
|
|
verbosity of PHP tends to obscure what is actually going on. To construct an array of objects, you actually need
|
|
an array of arrays:
|
|
|
|
[source,json]
|
|
----
|
|
$params['body'] = array(
|
|
'query' => array(
|
|
'match' => array(
|
|
'content' => 'quick brown fox'
|
|
)
|
|
),
|
|
'sort' => array( <1>
|
|
array('time' => array('order' => 'desc')), <2>
|
|
array('popularity' => array('order' => 'desc')) <3>
|
|
)
|
|
);
|
|
$results = $client->search($params);
|
|
----
|
|
<1> This array encodes the `"sort" : []` array
|
|
<2> This array encodes the `{"time" : {"order" : "desc"}}` object
|
|
<3> This array encodes the `{"popularity" : {"order" : "desc"}}` object
|
|
|
|
If you are on PHP 5.4+, I would strongly encourage you to use the short array syntax. It makes these nested arrays
|
|
much simpler to read:
|
|
|
|
[source,json]
|
|
----
|
|
$params['body'] = [
|
|
'query' => [
|
|
'match' => [
|
|
'content' => 'quick brown fox'
|
|
]
|
|
],
|
|
'sort' => [
|
|
['time' => ['order' => 'desc']],
|
|
['popularity' => ['order' => 'desc']]
|
|
]
|
|
];
|
|
$results = $client->search($params);
|
|
----
|
|
|
|
=== Arrays of empty objects
|
|
|
|
Occasionally, you'll encounter DSL that requires both of the previous patterns. The function score query is a good
|
|
example, it sometimes requires an array of objects, and some of those objects might be empty JSON objects.
|
|
|
|
Given this query:
|
|
[source,json]
|
|
----
|
|
{
|
|
"query":{
|
|
"function_score":{
|
|
"functions":[
|
|
{
|
|
"random_score":{}
|
|
}
|
|
],
|
|
"boost_mode":"replace"
|
|
}
|
|
}
|
|
}
|
|
----
|
|
|
|
We can build it using the following PHP code:
|
|
|
|
|
|
[source,json]
|
|
----
|
|
$params['body'] = array(
|
|
'query' => array(
|
|
'function_score' => array(
|
|
'functions' => array( <1>
|
|
array( <2>
|
|
'random_score' => new \stdClass() <3>
|
|
)
|
|
)
|
|
)
|
|
)
|
|
);
|
|
$results = $client->search($params);
|
|
----
|
|
<1> This encodes the array of objects: `"functions" : []`
|
|
<2> This encodes an object inside the array: `{ "random_score": {} }`
|
|
<3> This encodes the empty JSON object: `"random_score": {}`
|
|
|