Creating campaign for dynamic TextMerge segment fails - php

I'm trying to send a campaign to a dynamic list segment based on a custom numeric merge field (GMT_OFFSET, in this case) but the code below yields the following error from the MailChimp API:
"errors" => [
0 => [
"field" => "recipients.segment_opts.conditions.item:0"
"message" => "Data did not match any of the schemas described in anyOf."
]
]
My code, using drewm/mailchimp-api 2.4:
$campaign = $mc->post('campaigns', [
'recipients' => [
'list_id' => config('services.mailchimp.list_id'),
'segment_opts' => [
'conditions' => [
[
'condition_type' => 'TextMerge',
'field' => 'GMT_OFFSET',
'op' => 'is',
'value' => 2,
],
],
'match' => 'all',
],
],
],
// Cut for brevity
];
If I am to take the field description literally (see below), the TextMerge condition type only works on merge0 or EMAIL fields, which is ridiculous considering the Segment Type title says it is a "Text or Number Merge Field Segment". However, other people have reported the condition does work when applied exclusively to the EMAIL field. (API Reference)
I found this issue posted but unresolved on both DrewM's git repo (here) and SO (here) from January 2017. Hoping somebody has figured this out by now, or found a way around it.

Solved it! I passed an integer value which seemed to make sense given that my GMT_OFFSET merge field was of a Number type. MailChimp support said this probably caused the error and suggested I send a string instead. Works like a charm now.

Related

Elasticsearch - Want to sort by field in all indices where that particular field available or not if not then avoid it

Currently, Getting result based on scoring but what i want to do is i want a result based on scoring + Field Status with value true/false.
If value is true then needed that results in priority but there is possibility that status field is not exist in all indices.
"query" => [
'bool' => [
'filter' => $filter,
'must' => [
"multi_match" => [
'query' => "$string",
"type" => "cross_fields",
'fields' => ['field1','field2','field3'],
"minimum_should_match" => "80%"
]
]
]
],
"sort" => [
"_score",
[ "status" => ["order" => "desc","unmapped_type" => "boolean"] ]
],
But getting error below :
[type] => illegal_argument_exception
[reason] => Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [status] in order to load field data by uninverting the inverted index. Note that this can use significant memory.
Anyone help me out to ignore for indices where that field not available or any other solution with this problem?
As discussed in the chat, the issue happened due to #jilesh
forget to delete the old index mapping and only upate the data that's what this thing was occurring.
Below answer is relevant when you get below error with proper setup
Text fields are not optimised for operations that require
per-document field data like aggregations and sorting, so these
operations are disabled by default. Please use a keyword field
instead. Alternatively, set fielddata=true on [status] in order to
load field data by uninverting the inverted index. Note that this can
use significant memory.
In that case, please enable the field data on the field if you want to get rid of the error but beware it can cause performance issues.
Read more about the field data on official site.
You can enable it in your order field in your mapping as shown.
{
"properties": {
"order": {
"type": "text",
"fielddata": true
}
}
}
works for me
curl -X PUT -H "Content-Type: application/json" \
-d '{"properties": {"format": { "type":"text","fielddata": true}}}' \
<your_host>:9200/<your_index>/_mapping
In my case, I had to use the aggregatable {fieldname}.keyword field. Here's an example using Nest .NET.
.Sort(s => s
.Ascending(f => f.Field1.Suffix("keyword"))
.Ascending(f => f.Field2.Suffix("keyword"))
.Ascending(f => f.Field3.Suffix("keyword")))

Problem with 'Speficying custom values in Language Files'

I am working with a Laravel 5.8 version.
I need to modify the output of an error message form, unfortunately, the validation is not working properly.
The documentation says (https://laravel.com/docs/5.8/validation):
Specifying Custom Values In Language Files
Sometimes you may need the :value portion of your validation message to be replaced with a custom representation of the value. For example, consider the following rule that specifies that a credit card number is required if the payment_type has a value of cc:
$request->validate([
'credit_card_number' => 'required_if:payment_type,cc'
]);
If this validation rule fails, it will produce the following error message:
The credit card number field is required when payment type is cc.
Instead of displaying cc as the payment type value, you may specify a custom value representation in your validation language file by defining a values array:
'values' => [
'payment_type' => [
'cc' => 'credit card'
],
],
Now if the validation rule fails it will produce the following message:
The credit card number field is required when payment type is credit card.
I have a validation rule like:
$request->validate([
'foo' => [
'required_if:bar.bizz,1',
'numeric',
]
]);
And in my validation.php.
'values' => [
'bar.biz' => [
'1' => 'test',
],
'bar[biz]' => [
'1' => 'test',
],
'*.*' => [
'1' => 'test',
],
]
But I always get the same output:
The foo field is required when bar is 1.
Thanks.
Solved
If you are working in your form with arrays, you have also use arrays like:
'values' => [
'bar' => [
'biz' => [
'1' => 'test',
]
]
],
Also, note we are not using foo variable in the values array.
PS: The wildcard symbol (*) does not work.
Greetings.

How can I fetch results from elastic search from one column with different values at the same time?

I am using REST API using PHP for fetching data from Elastic search with following code
$params = [
'index' => $search_index,
'type' => $search_type,
'from' => $_POST["from"],
'size' => $_POST["fetch"],
'body' => [
'query' => [
'bool' => [
'must' => [
[ 'match' => [ 'is_validated' => false ] ],
[ 'query_string' => [ 'query' => $search_str, 'default_operator' => 'OR' ] ]
]
]
]
]
];
Now, this is working perfectly and giving me my desired results.
The data that is returned from ES, has one column "result_source" and it has predefined values like CNN, BBC or YouTube etc.
What I need is, I want to filter results on "result_source" column in a way that, I can only fetch the results with the option I want. Like I want results that have "result_source" value only "YouTube" or only "BBC & CNN" or only "CNN or YouTube" etc.
I have already tried "Should" option, but it also returns the data with other values that I don't need. Not sure how to skip those values of "result_source" column in fetching results from ES.
Any help on this will be appreciated.
Thanks
Solved!!
I am replying to my own question, because I found a solution for it. May be it can help someone else in future.
If anyone is looking for a solution of searching within the field / column of Elastic search, here is what can be done.
[ 'query_string' => [ 'query' => $search_str.'(result_source:CNN OR result_source:BBC)', 'default_operator' => 'OR' ] ]
"result_source" is actually the field / column name of ES on which filter is applied to return results that have result_source=BBC or result_source=CNN.
This actually solved my issue.

Elasticsearch. Data update and keeping history of previous values of fields

Part of my mapping is:
"current_price" => ["type" => "float"],
"price_history" => [
"type" => "nested",
"properties" => [
"date" => ["type" => "date"],
"value" => ["type" => "float"]
]
As you can see I keep in storage current price of goods and all the previous values. First thing I would like to notice is when I create goods in a very first time, I have no history, of course. That's why when I create goods, I do not use price_history at all, although it exists in my mapping.
$params = [
'index' => config('storesettings.esIndex'),
'type' => config('storesettings.esType'),
'id' => $id,
'body' => [
...
"current_price" => $request->get('current_price'),
...
]
];
When I edit goods, I change the price. In this case I need to move the current price to archive, moving it to price_history field. And then I need to replace current name. The question is about price_history field. I get previous value ($goods['_source']['price_history']) then I add to this array current_name. Everything is fine when I already have some history. But if I have not, then I get the error 'Undefined index: price_history'. In this case I should do checking: if(isset($goods['_source']['price_history'])). Is it normal? In relational databases I would have an empty array, but in Elasticsearch I haven't and I must do array level (so to speak) checking. How to handle such cases? Maby I should add an epmty array to price_history when I create goods?..

Elasticsearch exact match field

I have a field called url that is set to not_analyzed when I index it:
'url' => [
'type' => 'string',
'index' => 'not_analyzed'
]
Here is my method to determine if a URL already exists in the index:
public function urlExists($index, $type, $url) {
$params = [
'index' => $index,
'type' => $type,
'body' => [
'query' => [
'match' => [
'url' => $url
]
]
]
];
$results = $this->client->count($params);
return ($results['count'] > 0);
}
This seems to work fine however I can't be 100% sure this is the correct way to find an exact match, as reading the docs another way to do the search is with the params like:
$params = [
'index' => $index,
'type' => $type,
'body' => [
'query' => [
'filtered' => [
'filter' => [
'term' => [
'url' => $url
]
]
]
]
]
];
My question is would either params work the same way for a not_analyzed field?
The second query is the right approach. term level queries/filters should be used for exact match. Biggest advantage is caching. Elasticsearch uses bitset for this and you will get quicker response time with subsequent calls.
From the Docs
Exclude as many document as you can with a filter, then query just the
documents that remain.
Also if you observe your output, you will find that _score of every document is 1 as scoring is not applied to filters, same goes for highlighting but with match query you will see different _score. Again From the Docs
Keep in mind that once you wrap a query as a filter, it loses query
features like highlighting and scoring because these are not features
supported by filters.
Your first query uses match which is basically used for analyzed fields e.g when you want both Google and google to match all your documents containing google(case insensitive) match queries are used.
Hope this helps!!

Categories