How to search in all fields in ElasticSearch index? - php

{"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.

Related

Laravel how to use $request except on nested array

Is it possible to use $request->except on a nested array? This is the request data:
[▼
"id" => 1
"products" => array:1 [▼
0 => array:4 [▼
"id" => 1
"name" => "sample product"
"date" => "07/04/2022"
"frequency" => array:1 [ …1]
]
]
]
My goal is to remove some key value pairs e.g. removing id, date and frequency. My desired result would be:
[▼
"id" => 1
"products" => array:1 [▼
0 => array:1 [▼
"name" => "sample product"
]
]
]
What I've tried so far is to use Arr:except function:
$request->products = Arr::except($request->products['0'], ['id', 'date', 'frequency']);
But this should be applied on all items. Let's say I have two item products, the desired result would be:
[▼
"id" => 1
"products" => array:2 [▼
0 => array:1 [▼
"name" => "sample product"
]
1 => array:1 [▼
"name" => "sample product 2"
]
]
]
Need your inputs on what's the best approach for this. Thank you!
Unless I am missing something obvious, could you not just iterate over the products in your $request object?
$filtered = [];
foreach ($request->products as $product) {
$filtered[] = Arr::except($product, ['id', 'date', 'frequency']);
}
dd($filtered);
Resulting in $filtered containing:
^ array:2 [▼
"id" => 1
"products" => array:2 [▼
0 => array:1 [▼
"name" => "sample product"
]
1 => array:1 [▼
"name" => "sample product 2"
]
]
]
Update 1
I can see that the $request except only works on the top level
Not sure what you mean by this as the above principle works for me.
$filtered = [];
foreach ($request->products as $product) {
$filtered[] = Arr::except($product, ['id', 'date', 'frequency']);
}
$request->merge(['products' => $filtered]);
If I supply the above with the following:
{
"id": 1,
"products": [
{
"id": 1,
"name": "sample product",
"date": "07/04/2022",
"frequency": []
},
{
"id": 2,
"name": "sample product 2",
"date": "07/04/2022",
"frequency": []
}
]
}
Then do a dd($request->products); I get:
^ array:2 [▼
0 => array:1 [▼
"name" => "sample product"
]
1 => array:1 [▼
"name" => "sample product 2"
]
]

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.

Laravel 5.4 multiple (dynamic) form & square brackets

I use Laravel 5.4 and Laravel Collective's Form & HTML Builder (https://laravelcollective.com/docs/5.4/html).
I have a dynamic form, like this:
https://codepen.io/matedon/pen/BZQymW
There are more input fields with the same name but with square bracket:
<input name="apartments[][price]">
<input name="apartments[][rooms]">
<input name="apartments[][price]">
<input name="apartments[][rooms]">
With the Laravel Collective's Form & HTML Builder the output and the old() value should be that:
{
"apartments": [
{
"price": "23000",
"rooms": "12"
},
{
"price": "42000",
"rooms": "32"
}
]
}
But there is an issue and I got this:
#php(dump(Form::old('apartments')))
array:1 [▼
"price" => "23000"
]
I also tried Laravel's "native" solution which is wrong too:
#php(dump(session()->getOldInput('apartments')))
array:4 [▼
0 => array:1 [▼
"price" => "23000"
]
1 => array:1 [▼
"rooms" => "12"
]
2 => array:1 [▼
"price" => "42000"
]
3 => array:1 [▼
"rooms" => "32"
]
]
What is the solution could be?
Thank you!
You are just missing in the construction of the inputs, in case you want something like this:
"apartments" => array:2 [
"price" => array:2 [
0 => "52.5"
1 => "65"
]
"rooms" => array:2 [
0 => "3"
1 => "4"
]
]
Your inputs should look like:
<input name="apartments[price][]">
<input name="apartments[rooms][]">
<input name="apartments[price][]">
<input name="apartments[rooms][]">
If you need them to be separated by apartment you need to add some type of index (since it is a dynamic form you may need to keep the current index stored somewhere in your application):
"apartments" => array:2 [
1 => array:2 [
"price" => "52.5"
"rooms" => "3"
]
2 => array:2 [
"price" => "65"
"rooms" => "4"
]
]
Your inputs:
<input name="apartments[1][price]">
<input name="apartments[1][rooms]">
<input name="apartments[2][price]">
<input name="apartments[2][rooms]">
Note that this is not the framework fault, it is more a form structure issue. If you need more information about how to build form datasets I'd recommend you to check W3C HTML5 Forms section.
Hope this helps you.

ElasticSearch fulltext search with bool query

I am trying to make full-text search in whole document using
"query" => [
"query_string" => [
"fields" => ["_all"],
"query" => "fooA AND fooB"
]
]
It works pretty good. In the same query I need to run bool query
"query" => [
"bool" => [
"must" => [
"term" => [
"name" => "My_name"
]
],
"should" => [
....
]
]
]
Is it possible to combine these two queries ? is this proper way to make full-text search ?
In result I need all documents that contains "fooA AND fooB" in any field and special field name equals "My_name".
I found solution for my question thanks to this post.
"query" => [
"bool" => [
"must" => [
[
"term" => [
"name" => "My_name"
]
],
[
"query_string" => [
"fields" => ["_all"],
"query" => "fooA AND fooB"
]
]
]
]
]
This combination works for me
Yes, you can club these together as shown below :
GET _search
{
"from": 0,
"size": 20,
"query": {
"bool": {
"must": [
{
"term": {
"name": "MY_NAME"
}
},
{
"query_string": {
"query": "fooA AND fooB",
"fields": [
"_all"
]
}
}
]
}
}
}

Elastic search with space

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

Categories