I'm working on elasticsearch (2.3) and am trying to create a search query. For elasticsearch I need JSON, but I start with a simple php array and encode it to JSON afterwards.
I have a problem with creating the right array format.
This is a small part of the code I'm using:
$params['body']['query']['filtered']['filter']['bool']['must']["term"]['pprCategories']= "category1";
$params['body']['query']['filtered']['filter']['bool']['must_not']['exists']['field'] = "field1";
With an if statement I add a new line:
$params['body']['query']['filtered']['filter']['bool']['must']['term']['country_name']= "country1";
So the total code is:
$params['body']['query']['filtered']['filter']['bool']['must']["term"]['pprCategories']= "category1";
$params['body']['query']['filtered']['filter']['bool']['must_not']['exists']['field'] = "field1";
$params['body']['query']['filtered']['filter']['bool']['must']['term']['country_name']= "country1";
#output
echo "<pre>";
print_r(json_encode($params, JSON_PRETTY_PRINT));
echo "</pre>";
The is the actual result I get from the query I built:
{
"body": {
"query": {
"filtered": {
"filter": {
"bool": {
"must": {
"term": {
"pprCategories": "category1",
"country_name": "country1"
}
},
"must_not": {
"exists": {
"field": "field1"
}
}
}
}
}
}
}
}
However, the desired result would be as follows, i.e. with two elements in the bool/must array:
{
"body": {
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"pprCategories": "category1"
}
},
{
"term": {
"country_name": "country1"
}
}
],
"must_not": {
"exists": {
"field": "field1"
}
}
}
}
}
}
}
}
As you can see the bool/must array contains two conditions instead of just one: pprCategories and country_name are two different 'must' conditions.
Thanks for helping me out!
If you want to add several conditions, you need to understand that bool/must should be an array. You can make your code work like this:
// first create the bool/must array with a single term condition
$params['body']['query']['filtered']['filter']['bool']['must'] = [
[
'term' => [
'pprCategories' => "category1";
]
]
];
// add the must_not condition
$params['body']['query']['filtered']['filter']['bool']['must_not']['exists']['field'] = "field1";
// test your condition
if (...) {
// now add a second constraint to the bool/must array
$params['body']['query']['filtered']['filter']['bool']['must'][] = [
'term' => [
'country_name' => "country1"
]
];
}
I think you should be going this way before taking it to json.
$params['body']['query']['filtered']['filter']['bool']['must'][0]["term"]['pprCategories']= "category1";
$params['body']['query']['filtered']['filter']['bool']['must'][1]["term"]['country_name']= "country1";
$params['body']['query']['filtered']['filter']['bool']['must'][2]["term"]['population_name']= "population1";
$params['body']['query']['filtered']['filter']['bool']['must'][3]["term"]['kilometers_amount']= "55145";
Related
I'm trying to fetch a mongodb data using PHP.
My Data is in the following format:
$document = $collection->findOne(
array('_id' => 'set1'),
array('projection' => array('_id' => 1,'data'=>1))
);
Result:
{
"_id": "set1",
"data": {
"IND": {
"2015-01": 0.6753404,
"2015-02": 1.0502269,
"2015-03": 1.0902269
},
"AUS": {
"2015-01": 0.6753404,
"2015-02": 1.0502269,
"2015-03": 1.0902269
},
"IND_123": {
"2015-01": 0.6753404,
"2015-02": 1.0502269,
"2015-03": 1.0902269
}
}
}
I am trying to fetch the output such that the result only has "IND" and "IND_123".
Is there a way to write the projection such that the result only provides "IND*"
The following provides only "IND"
$document = $collection->findOne(
array('_id' => 'set1'),
array('projection' => array('_id' => 1,'data.IND'=>1))
);
You can achieve it using an aggregation pipeline, like this:
db.collection.aggregate([
{
"$match": {
"_id": "set1"
}
},
{
"$project": {
data: {
"$arrayToObject": {
"$filter": {
"input": {
"$objectToArray": "$data"
},
"as": "item",
"cond": {
"$regexMatch": {
"input": "$$item.k",
"regex": "IND.*"
}
}
}
}
}
}
}
])
Playground link.
Here, we match the required document using $match. Then we, recompute the data field in $project, we first convert the data object to an array using $objectToArray, and filter all keys matching the pattern IND.* using $filter. Finally, we convert the filtered array back to an object using $arrayToObject.
I've got the following data structure:
Array -> Object -> Array -> Object -> Object
[
{
"id":6834,
"contract_id":13,
"schedule_column_values":[
{
"id":34001,
"field_value":{
"id":324241,
"value":10,
"field":{
"id":1,
"signature":"ios"
}
}
},
{
"id":34001,
"field_value":{
"id":324241,
"value":10,
"field":{
"id":1,
"signature":"android"
}
}
}
]
}
]
What I'm trying to achieve is that if a field has the signature of "android", remove its grandparent object from schedule_column_values. Basically, if a signature is "android", the final data would look like this:
[
{
"id": 6834,
"contract_id": 13,
"schedule_column_values": [
{
"id": 34001,
"field_value": {
"id": 324241,
"value": 10,
"field": {
"id": 1,
"signature": "ios"
}
}
}
]
}
]
This is just an example but the structure is always the same and we always know what signature we're looking for. It could be anything other than android but we know the string we're looking for.
I've tried a nested foreach loop and tried unset but it doesn't seem to work. The other way is I've set a NULL to object value of schedule_column_values when the signature of field is matched, but I cannot have NULL in the object.
What would be a good way to filter out this structure?
This is a perfect use case for array_filter:
$filtered_array = [];
foreach($array as $grandparent){
$filtered_schedules = array_filter(
$grandparent->schedule_column_values,
function($item){
return $item->field_value->field->signature !== 'android';
}
);
$altered_grandparent = clone $grandparent;
$altered_grandparent->schedule_column_values = $filtered_schedules;
$filtered_array[] = $altered_grandparent;
}
My model has many options, multiple fields of a single option store values as an array on integers.
I want to filter based on an integer is included.
in php similare to in_array(), but the array is stored in db, and the number is key word.
$productsWithOptions = [
{
"id":2,
"name":"mac 2",
"options":[
{
"id":4,
"price":99.9,
"product_id":2,
"colors":"[4,3,2]",
"sizes":"[5,3,2]"
},
{
"id":5,
"price":99.9,
"product_id":2,
"colors":"[4,4,5]",
"sizes":"[1,2,2]"
},
{
"id":7,
"name":"mac 7",
"options":[
{
"id":19,
"price":99.9,
"product_id":7,
"colors":"[6,3,4]",
"sizes":"[5,2,5]"
},
{
"id":20,
"price":1999.9,
"product_id":7,
"colors":"[1,6,6]",
"sizes":"[5,6,2]"
},
{
"id":21,
"price":1999.9,
"product_id":7,
"colors":"[4,6,5]",
"sizes":"[5,2,2]"
}
]
}
]
$products = Product::whereHas('options', function (Builder $query) use ($arr) {
$query->where('colors','like', "%2%" );
})->get();
This is how options table looks like in db.
I have a nested array from a json API that usually have zero, one, or two arrays.
I can get it so if the array is empty to display "N/A", and to display only the first ([0]) instance of the array.
However displaying the second array is tripping me up. I know I need to use the foreach to iterate through the PosTags (see below) array, so to extract each Tag value in the body of the foreach loop. However, I can't figure HOW to do this correctly.
My JSON:
[
{
"SectionDetails": [
{
"Description": "Course Description",
"Departments": "Department",
"Credits": "3.00",
"Meetings": [
{
"DOW": "Th",
"Dates": "08-31-2017 to 12-08-2017",
"Times": "03:00 PM - 05:30 PM",
}
],
"PosTags": [
{
"Tag": "HART-ANC"
},
{
"Tag": "ARCH-ARCH"
}
]
}
]
}
]
Current PHP:
$postag = "N/A";
if (isset($sectiondetails->{'PosTags'}))
{
if(!empty($sectiondetails->{'PosTags'})) {
$postag=$sectiondetails->{'PosTags'}[0]->{'Tag'};
}
}
Running a foreach loop like the following displays "Object of class stdClass could not be converted to string" on the line where echo tag is:
if (isset($sectiondetails->{'PosTags'})) {
if(!empty($sectiondetails->{'PosTags'})) {
$postag=$sectiondetails->{'PosTags'};
foreach ($postag as $tag) {
echo $tag;
}
}
}
Ideally I'd like HART-ANC, ARCH-ARCH to be displayed. Thoughts?
I have created a small dataset (currently only 8 items) in an Elastic Search index.
The entries are structured as follows
{
"value_a": "Foo",
"value_b": "Bar",
"value_c": "Baz"
}
In Elastic Search this then looks as follows (taken from querying my Elastic Search endpoint directly) :
{
"_index": "foo_bar_bazindex",
"_type": "foo_bar_baz",
"_id": "4",
"_score": 1,
"_source": {
"value_a": "Foo",
"value_b": "Bar",
"value_c": "Baz"
}
}
The combinations of value a, b and c are unique.
I want to find the values of "value_c" by performing a bool filtered search with the values a and b.
In my code I have been trying this as follows:
$filter = new \Elastica\Filter\Bool();
$query = new \Elastica\Query();
$aFilter = new \Elastica\Filter\Term(['value_a' => "Foo"]);
$bFilter = new \Elastica\Filter\Term(['value_b' => "Bar"]);
$filter->addMust($aFilter);
$filter->addMust($bFilter);
$query->setFilter($filter);
$results = $this->bookingPeriodIndex->search($query)->getResults();
var_dump($results);
However this returns no results (the var dump outputs an empty array) - also manually trying this query by posting this query directly to the server:
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"value_a": "Foo"
}
},
{
"term": {
"value_b": "Bar"
}
}
]
}
}
}
}
}
This also yields no results - I would however expect it to return one result as I have the following entry:
{
"value_a": "Foo",
"value_b": "Bar",
"value_c": "Baz"
}
Am I missing something? Could it be due to the small dataset? We use the same Bool Filter Elastica queries elsewhere in our codebase and these work as expected, however I cannot seem to get any data to return from this index.
Any help would be appreciated.
In the end I got the results I was looking for by using a bool query with two match statements:
The raw query:
{
"query": {
"bool": {
"must": [
{
"match": {
"value_a": "Foo"
}
},
{
"match": {
"value_b": "Bar"
}
}
]
}
}
}
The query using Elastica:
$query = new Query;
$booleanQuery = new Bool();
$fooMatch = new Match();
$fooMatch->setField('value_a', 'Foo');
$booleanQuery->addMust($fooMatch);
$barMatch = new Match();
$barMatch->setField('value_b', 'Bar');
$booleanQuery->addMust($barMatch);
$query->setQuery($booleanQuery);
$results = $this->index->search($query)->getResults();