Elastic search with space - php

I have a Elasticsearch setup which will allow user to search indexes as wild cards.
array:3 [
"index" => "users"
"type" => "user"
"body" => array:4 [
"from" => 0
"size" => 25
"sort" => array:1 [
1 => array:1 [
"order" => "asc"
]
]
"query" => array:1 [
"bool" => array:1 [
"should" => array:1 [
0 => array:1 [
0 => array:1 [
"wildcard" => array:1 [
"full_name" => "john doe"
]
]
]
]
]
]
]
]
when I pass this array to search function, it is returning an empty array. But there is a document related to "John Doe" and when I run "full_name" => "john" search is returning the document.
I feel that the problem is with the space.
{
"users": {
"user": {
"properties": {
"address": {
"type": "string"
},
"full_name": {
"type": "string"
},
"industry_name": {
"type": "string"
}
}
}
}
}

Assuming field full_name is analyzed by elasticsearch.
The problem in your case is fact that wildcard query doesn't analyze search string
Matches documents that have fields matching a wildcard expression (not
analyzed).
In you case it means, that elasticsearch stored john and doe tokens in inverted index, but wildcard query is searching for john doe token, and it fails.
What you can do about this:
Change index mapping, so full_name filed is not analyzed anymore.
Note: you will have to search for John Doe to get match, because
value wasn't analyzed so john doe won't match.
You can improve first solution, just by leaving full_name
analyzed, but with custom analyzer(wildcard, lowercase). It will
allow you to search for text john doe or John Doe.
{
"settings" : {
"index" : {
"analysis" : {
"analyzer" : {
"lowercase_analyzer" : {
"tokenizer" : "keyword",
"filter" : [
"lowercase"
],
"type" : "custom"
}
}
}
}
},
"mappings" : {
"user" : {
"properties" : {
"id" : {
"type" : "integer"
},
"fullName" : {
"analyzer" : "lowercase_analyzer",
"type" : "string"
}
}
}
}
}
You can take advantage of multi field, and search against raw
field.
"full_name.raw" => "John Doe"
Hope it will help you handle your use case.
UPDATE
Here you can find more information how to control index mapping.

I think standard tokenizer will be applied by default.
In that case, it will consider the text john doe as phrase.
So try phrase search
"full_name" => "\"john doe\""

If you want to consider spaces you could do something like:
{
"match" : {
"full_name" : {
"query" : "john doe",
"operator" : "and",
"zero_terms_query": "all"
}
}
}
check this: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html

Related

How to search in all fields in ElasticSearch index?

{"cf_items":{"aliases":{},"mappings":{"properties":{"CFDocumentURI":{"properties":{"identifier":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"title":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"uri":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}}}},"CFItemType":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"CFItemTypeURI":{"properties":{"identifier":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"title":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"uri":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}}}},"educationLevel":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"fullStatement":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"humanCodingScheme":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"identifier":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}},"lastChangeDateTime":{"type":"date"},"uri":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}}}},"settings":{"index":{"routing":{"allocation":{"include":{"_tier_preference":"data_content"}}},"number_of_shards":"1","provided_name":"cf_items","creation_date":"1654520558130","number_of_replicas":"1","uuid":"wMIBuI59QoWhR2-p69ER8Q","version":{"created":"7130099"}}}}}
and I want to search inside any field with matching keyword? How can I do that?
I tried below way
array:2 [
"index" => "cfitems-*"
"body" => array:1 [
"query" => array:1 [
"bool" => array:1 [
"should" => array:1 [
0 => array:1 [
"match_all" => array:1 [
0 => "Default"
]
]
]
]
]
]
]
but not working
use multi-match query
{
"query": {
"multi_match" : {
"query": "Will Smith",
"fields": ["*"] // for all fields or pass in specific fields
}
}
}
I don't see you have many fields in your index. you can use the multi-match query which also supports the wildcard in the fields name.
Refer fields with wildcard example from official Elasticsearch document.

How to check if an element exist in array of array in php

please I am trying to regroup the array based on the course. Instead of 0,1,2 etc. For example, check if "Elementary Economics" exist in all the array, then it should return the result of all the array elements that match "Elementary Economics".
student => [
0 => [
"name" => "John Doe",
"gender" => "Male",
"department" => "Economics",
"courses" => [
"Elementary Economics",
"Principle of Economics",
"Macro Economics"
"Money Market"
]
],
1 => [
"name" => "John Doe",
"gender" => "Male",
"department" => "Economics",
"courses" => [
"Advanced Economics",
"Principle of Economics",
"Micro Economics"
"Money Market"
]
]
2 => [
"name" => "John Doe",
"gender" => "Male",
"department" => "Economics",
"courses" => [
"Elementary Economics",
"Principle of Economics",
"Macro Economics"
"Value Market"
]
]
]
I want to group them by the course, I have tried to used array_filter, it didn't work as I intend or maybe I was doing it wrong.
$result = array_filter($student, function ($item) use ($student['courses']) {
return \in_array($item, $student['courses'], true);
}, \ARRAY_FILTER_USE_KEY);
I was able solve my issue by installing and using array-group-by
$ composer require mcaskill/php-array-group-by
$grouped = array_group_by( $student, "course" );

PHP+PSR7: getParsedBody() always convert empty strings on json to null

I'm im using zendframework/zend-diactoros with Laravel. I have a problem when I sent json data like
{
"data": {
"value": ""
}
}
Then, in controller
// #var $request Psr\Http\Message\ServerRequestInterface
var_dump($request->getParsedBody())
/*
array:1 [
"data" => array:1 [
"value" => null // I expect "value" => ""
]
]
More examples:
I sent
{
"data": {
"value": null
}
}
var_dump
var_dump($request->getParsedBody())
/*
array:1 [
"data" => array:1 [
"value" => null // that's OK
]
]
I sent
{
"data": {
"value": "x"
}
}
var_dump
var_dump($request->getParsedBody())
/*
array:1 [
"data" => array:1 [
"value" => "x" // that's OK
]
]
Only first example has a problem, but I dont have any idea if this is correct. Maybe exists a way to dump exact received data with this PSR7 library.

yii2 mongodb update embedded array

How to update members age whose name is TEST1 using yii2.?
Used below code to update , but i am specifying the indexes there , i want with out specifying the indexes.
User::updateAll([ '$set'=> ['Addresses.0.members.0.age'=>100] ],['IN','Addresses.members.name',['TEST1'] ]);
{
"_id" : ObjectId("595209b65312f48195fb2e01"),
"username" : "Test name",
"Addresses" : [
{
"address_no" : 1,
"Address" : "Test house",
"City" : "test city",
"State" : "Test state",
"Mobile" : "9999999",
"members" : [
{
"name" : "TEST1",
"age" : 35
},
{
"name" : "TEST2",
"age" : 30
},
]
},
{
"address_no" : 2,
"Address" : "2B, Test place",
"City" : "Test city",
"State" : "Test State",
"Pincode" : "12345",
"Phone" : "1234568789",
"Mobile" : 9999999999
}
],
"Beneficiaries" : [
{
"beneficiary_id" : 1,
"Name" : "Test1",
"Age" : "28",
"Sex" : "F"
}
],
"auth_key" : "esd8d89ds89ds89ds89ds",
}
there is position operator $ to do this kind of job
{
"Addresses.members.name" : "TEST2",
},
{
$set: {
"Addresses.$.members.0.age" : 40
}
}
Here I specified first index as it supports up to one level depth.
New feature might release in future to resolve this issue: https://jira.mongodb.org/browse/SERVER-831
Yii::$app->mongodb->getCollection('user')->update(['_id' => $id, 'members.name' => 'Test1'], ['$set' => [
'members.$.age' => 100,
]]);

MongoDB update sub document issue

I'm having Mongo structure like this,
"campaigns":[{
"summary" :
[ {
"postcode" : [ {
"id" : "71",
"name" : "Recall 1",
"qty" : 3,
"history" :
[ { "timestamp" : "2014-12-16 11:15:32",
{ "timestamp": "2014-12-16 11:15:53"
} ]
} ]
},
{
"postcode" :
[ {
"id" : "72",
"name" : "Recall 2",
"qty" : 1,
"history" : [ { "timestamp" : "2014-12-16 11:15:53" } ]
} ]
}]
I'm trying to i) increment qty of postcode.id : 72 ii) insert another timestamp for that same postcode id 72.
My code:
$collection->update(array("campaigns.task.id" => $b,"_id"=> new MongoId($objectid),"campaigns.0.summary.0.postcode.0.id" => $a), array('$inc' => array('campaigns.0.summary.0.postcode.0.qty' => 1)));
$collection->update(array("campaigns.task.id" => $b,"_id"=>new MongoId($objectid),"campaigns.0.summary.0.postcode.0.id" => $a),
array('$addToSet' => array('campaigns.0.summary.0.postcode.0.history' => array("timestamp"=>$now->format('Y-m-d H:i:s')))));
but postcode.id = 72 not gets updated, i'm confused with this nested subdocument can anyone suggest me the solution ?

Categories