Filter data from field name on elasticsearch-PHP


#1

I have written an index on Elasticsearch with following fields.

    $indexData = [
    'index' => 'profiles',
    'type' => 'profile',
    'body' =>[
                            'id' => $data->id,
                            'first_name' => (string)$data->first_name,
                            'last_name' => (string)$data->last_name,
                            'phone_mobile' => $data->phone_mobile,
                             'phone_work' => $data->phone_work,
                            'company_name' => $data->company_name,   
                         ]
                   ];
        $indexed = $profileElastic->addIndex($indexData);

I have managed to filter them using "more_like_this". But i need to filter them using the Field Name.

Example: Searching value is : 456 and field is:phone_mobile. Scenario: First i Need to check that 'phone_mobile' column is blank or not, if it is not blank, then check whether 'phone_mobile' column has the value '456',if it is true, return the corresponding Data Set.

If it is 'phone_mobile' field is blank, then i need to check 'phone_work' is null or not.if null return empty,otherwise continue the checking.

hope i have explained clearly.
Thanks in Advance for any help


(Camilo Sierra) #2

you can do that with a should, for this you need to use exist filter (http://www.elastic.co/guide/en/elasticsearch/reference/1.3/query-dsl-exists-filter.html) be sure to set to null if empty phone_mobile or phone_work.

{
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "should": [
            {
              "exists": {
                "phone_mobile": "465"
              }
            },
            {
              "exists": {
                "phone_work": "465"
              }
            }
          ],
          "minimum_number_should_match": 1
        }
      }
    }
  }
}

#3

is this the way to write the php for that?

    $query = $es->search([
	'body' =>[
		'query' =>[
			'bool'=>[
				'should' =>[
					'exists' =>['phone_mobile' =>'456'],
					'exists' =>['phone_home'=>'456'] 
					
				]
			]
		]
	]
]);

and how to specify the
"minimum_number_should_match": 1


(Camilo Sierra) #4

it will be something more like :

   [
    'body'=>[
        'filtered'=>[
            'filter'=>[
                'bool'=>[
                    'should'=>[
                        ['exists'=>[
                            'phone_mobile'=>'456'
                        ]],
                        ['exists'=>[
                            'phone_home'=>'456'
                        ]]
                    ],
                    "minimum_number_should_match"=>1
                ]
            ]
        ]
    ]
]

for me, the most easy way to work in php is to first create the query in json, and once this query works in elasticsearch and you get the result that you want, you can traduce this json in array. (to test your json query you can check the plugin head (any request))


#5

Hi there,
Thanks for the reply.Can you tell me how to pass created json query into elasticsearch?.any link which helps on json convert into php on ES?


(Zachary Tong) #6

The ES-PHP client supports raw JSON. See the documentation here: http://www.elastic.co/guide/en/elasticsearch/client/php-api/current/_search_operations.html

$json = '{
    "query" : {
        "match" : {
            "testField" : "abc"
        }
    }
}';

$params['index'] = 'my_index';
$params['type']  = 'my_type';
$params['body']  = $json;

$results = $client->search($params);

That said, I would not use raw JSON outside of prototyping/test. It is not very flexible, and easy to make mistakes. To become more familiar with the array representation, you can json_decode() the raw JSON string into an array, to learn how it transforms:

$json = '{
    "query" : {
        "match" : {
            "testField" : "abc"
        }
    }
}';

$transformed = json_decode($json, true);
print_r($transformed);

(Camilo Sierra) #7

and to test your json query in your elasticsearch you can download http://mobz.github.io/elasticsearch-head/ and in the tab Any Request you can paste your json and execute.


#8

Hi Camilo_Sierra and polyfractal,
Thanks for your really help full answers.
I have managed to write the search using this array as for the searching json.

[
'body'=>[
    'filtered'=>[
        'filter'=>[
            'bool'=>[
                'should'=>[
                    ['exists'=>[
                        'phone_mobile'=>'456'
                    ]],
                    ['exists'=>[
                        'phone_home'=>'456'
                    ]]
                ],
                "minimum_number_should_match"=>1
            ]
        ]
    ]
]

]

and i am passing this array to the search function like this,

$queryResponse = $globalElastic->search( [
'body'=>[
    'filtered'=>[
        'filter'=>[
            'bool'=>[
                'should'=>[
                    ['exists'=>[
                        'phone_mobile'=>'456'
                    ]],
                    ['exists'=>[
                        'phone_home'=>'456'
                    ]]
                ],
                "minimum_number_should_match"=>1
            ]
        ]
    ]
]

]);

an error comes up.BadRequest400Exception
any particular reason for this>?


(Camilo Sierra) #9

oh @DamPe my bad, the filter don't have minimum_number_should_match ! this options is only used in query. you can delete this option and your request will work!


#10

@Camilo_Sierra:Still doesn't work.

{"error":"SearchPhaseExecutionException[Failed to execute phase [query]

(Camilo Sierra) #11

ok , the query will be more complicate but it works

{
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "should": [
            {
              "bool": {
                "must": [
                  {
                    "exists": {
                      "field": "phone_mobile"
                    }
                  },
                  {
                    "term": {
                      "phone_mobile": 465
                    }
                  }
                ]
              }
            },
            {
              "bool": {
                "must": [
                  {
                    "exists": {
                      "field": "phone_home"
                    }
                  },
                  {
                    "term": {
                      "phone_home": 465
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    }
  }
}

(Camilo Sierra) #12

@DamPe if you don't use the aggregations and you like to filter only your hits, you can delete "query" and "filtered" and keep only the filter level


#13

@Camilo_Sierra: now it is giving me this error.

ErrorException in AbstractEndpoint.php line 299:
Invalid argument supplied for foreach()

This file is in here:

at HandleExceptions->handleError('2', 'Invalid argument supplied for foreach()', '/web/api/vendor/elasticsearch/elasticsearch/src/Elasticsearch/Endpoints/AbstractEndpoint.php', '299', array('params' => null)) in AbstractEndpoint.php line 299

#14

@Camilo_Sierra: I have sorted out the above error.
but now this error pops out.

"query" is not a valid parameter. Allowed parameters are: "analyzer", "analyze_wildcard", "default_operator", "df", "explain", "fields", "from", "ignore_unavailable", "allow_no_indices", "expand_wildcards", "indices_boost", "lenient", "lowercase_expanded_terms", "preference", "q", "routing", "scroll", "search_type", "size", "sort", "source", "_source", "_source_exclude", "_source_include", "stats", "suggest_field", "suggest_mode", "suggest_size", "suggest_text", "timeout", "version", "ignore", "custom", "curlOpts"

(Camilo Sierra) #15

it is probable that the problem come to your php code when you use the client search, to be sure that it's not the query the problem use a simple query that you already know that it works and replace it in your code!

if it doesn't works its your code php !


(Camilo Sierra) #16

i think so that the problem its that you put the query that i send you without the "body" level ?

    $queryResponse = $globalElastic->search( [
    'body'=>[
        "and hear the query that i send you (transformed in array off course)"
] ] );

#17

@Camilo_Sierra:Yes i have used without the body tag.
The Query you sent me has to transformed using json_decode() right?


(Camilo Sierra) #18

yes use json_decode($query, true);


#19

@Camilo_Sierra:Thanks for Great Help.Now its work.
Anyway i have a question:
can you explain these lines?.

 "bool": {
            "must": [
              {
                "exists": {
                  "field": "phone_mobile"
                }
              },
              {
                "term": {
                  "phone_mobile": 465
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "exists": {
                  "field": "phone_home"
                }
              },
              {
                "term": {
                  "phone_home": 465
                }
              }
            ]
          }

in this query what is exactly happening?.Sorry for the trouble mate.


(Camilo Sierra) #20

ok firstable i see that we can do something easier.
and after i will explain you both :

   {
    "filter": {
        "bool": {
            "should": [
                {
                    "term": {
                        "phone_mobile": 465
                    }
                },
                {
                    "term": {
                        "phone_home": 465
                    }
                }
            ]
        }
    }
}