-
Notifications
You must be signed in to change notification settings - Fork 964
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[DOCS] Add explanation of common JSON patterns in PHP
- Loading branch information
1 parent
f82569f
commit 36861fb
Showing
2 changed files
with
163 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
|
||
== 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": {}` |