Wiremock: how to validate ALL objects in an array - wiremock

Using wiremock-standalone (version 2.29.1), I want to verify a request with its body holding an array of objects, containing optional properties.
For instance, consider this request:
Request body (JSON format)
{
"foo": [
{ "bar": "1" },
{ "qux": "oh hai" },
{ "bar": "ohnoes" }
]
}
And let's say I want to match requests only if all the foo.bar attributes are either present, or contain only a single digit (it's only for the sake of example). The example above should not match (the third object has a bar attributes with non-digits characters).
I tried different approches, and the closest I got is this:
{
"matchesJsonPath": {
"expression": "$.foo[*].bar",
"or": [
{ "matches": "^\\d$" },
{ "absent": true }
]
}
}
There are 2 problems:
if there is no bar attribute at all, the request does not match
if at least 1 bar attribute passes the check, then the whole request passes, even though other bar values are invalid (the example above passes)
Does anyone know how to create such a rule in wiremock?

I found a possible solution, maybe not the easiest but it works.
Following your example:
request:
{
"foo": [
{ "bar": "1" },
{ "qux": "oh hai" },
{ "bar": "ohnoes" }
]
}
This bodyPatterns file works for validate each field is present and it has the value given:
"bodyPatterns" : [
{
"matchesJsonPath": "$.foo[?(#.bar == '1')]"
},
{
"matchesJsonPath": "$.foo[?(#.qux == 'oh hai')]"
},
{
"matchesJsonPath": "$.foo[?(#.bar == 'ohnoes')]"
}
]
For reference, the following post helped me a lot:
Wiremock matchesJsonPath checking array values ignoring the order

Related

How to search in ElasticSearch the most common word of a single field in a single document?

How to search in ElasticSearch the most common word of a single field in a single document? Lets say I have a document that have a field "pdf_content" of type keyword containing:
"good polite nice good polite good"
I would like a return of
{
word: good,
occurences: 3
},
{
word: polite,
occurences: 2
},
{
word: nice,
occurences: 1
},
How is this possible using ElasticSearch 7.15?
I tried this in the Kibana console:
GET /pdf/_search
{
"aggs": {
"pdf_contents": {
"terms": { "field": "pdf_content" }
}
}
}
But it only returns me the list of PDFs i have indexed.
Have you ever tried term_vector?:
Basically, you can do:
Mappings:
{
"mappings": {
"properties": {
"pdf_content": {
"type": "text",
"term_vector": "with_positions_offsets_payloads"
}
}
}
}
with your sample document:
POST /pdf/_doc/1
{
"pdf_content": "good polite nice good polite good"
}
Then you can do:
GET /pdf/_termvectors/1
{
"fields" : ["pdf_content"],
"offsets" : false,
"payloads" : false,
"positions" : false,
"term_statistics" : false,
"field_statistics" : false
}
If you want to see other information, you can set them to true. Set all to false give you what you want.

How to write jsonlogic.js rule that test an object against all objects in array (some)?

I have data for jsonlogic rule:
{ "component": { "tableNumber": 102}, "refcomponents": [ { "tableNumber": 102}, {"tableNumber": 302} ] }
and i need to check if component's tableNumber is found in refcomponents array. Can this be done? If not what would be a workaround?
Following rule does not work because var is relative to items in refcomponent-array:
{ "some" : [ { "var": "refcomponents" }, { "==" : [{ "var": "component.tableNumber"} , { "var" : "tableNumber" }]}]}
so component.tableNumber is null and is never evaluated true.
Thanks!

How do I use the Echonest API Start Parameter?

I am following the examples located on the following page:
http://developer.echonest.com/docs/v4/genre.html#artists
I'd like to offset the results from a search for artists by genre. The example they provide on the page listed "results" and "start". I assume "start" is the offset. The example query they provide is:
http://developer.echonest.com/api/v4/genre/artists?api_key=JEXNQ223JXCCQEINO&format=json&results=5&start=0&bucket=hotttnesss&name=jazz
But I get any error stating the "start" is an invalid parameter. Has anyone been able to use the "start" parameter with success?
This looks like a bug in their example. If you read the documentation, "start" and "results" are not valid for the genre/artists endpoint. Changing the example to remove these to parameters works.
Calling:
http://developer.echonest.com/api/v4/genre/artists?api_key=*********&format=json&bucket=hotttnesss&name=jazz
(replace the *** with your Key)
Yields:
{
"response":{
"status":{
"version":"4.2",
"code":0,
"message":"Success"
},
"artists":[
{
"name":"John Coltrane",
"hotttnesss":0.588225,
"id":"ARIOZCU1187FB3A3DC"
},
{
"name":"Thelonious Monk",
"hotttnesss":0.649332,
"id":"AR9PLH11187FB58A87"
},
{
"name":"Miles Davis",
"hotttnesss":0.697302,
"id":"AR7RTGF1187FB38793"
},
{
"name":"Miles Davis Quintet",
"hotttnesss":0.489603,
"id":"AR5DF1C1187FB4E94C"
},
{
"name":"Cannonball Adderley",
"hotttnesss":0.560071,
"id":"ARQ5TM41187FB3E97D"
},
{
"name":"Wayne Shorter",
"hotttnesss":0.548165,
"id":"ARO3CKW1187B9905A8"
},
{
"name":"Wynton Marsalis",
"hotttnesss":0.566708,
"id":"ARV3VEI1187B9AD5C9"
},
{
"name":"Sonny Rollins",
"hotttnesss":0.577764,
"id":"AR6Q4T91187B995616"
},
{
"name":"The Dave Brubeck Quartet",
"hotttnesss":0.570099,
"id":"ARLKR161187FB50694"
},
{
"name":"Kenny Burrell",
"hotttnesss":0.543388,
"id":"ARQYH461187FB3E975"
},
{
"name":"Stan Getz",
"hotttnesss":0.559735,
"id":"ARMGQLA1187B9AEBF8"
},
{
"name":"Dizzy Gillespie",
"hotttnesss":0.561122,
"id":"ARXA17J1187FB3B507"
},
{
"name":"Yusef Lateef",
"hotttnesss":0.513261,
"id":"ART95BW1187FB3AF79"
},
{
"name":"Bill Evans",
"hotttnesss":0.581819,
"id":"ARTLL9E1187FB4436F"
},
{
"name":"Freddie Hubbard",
"hotttnesss":0.524227,
"id":"ARU1K2U1187FB48529"
}
]
}
}
As far as I can tell, there isn't a way to page through the artists associated with a genre...

Elasticsearch: Find substring match

I want to perform both exact word match and partial word/substring match. For example if I search for "men's shaver" then I should be able to find "men's shaver" in the result. But in case case I search for "en's shaver" then also I should be able to find "men's shaver" in the result.
I using following settings and mappings:
Index settings:
PUT /my_index
{
"settings": {
"number_of_shards": 1,
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 20
}
},
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
}
}
Mappings:
PUT /my_index/my_type/_mapping
{
"my_type": {
"properties": {
"name": {
"type": "string",
"index_analyzer": "autocomplete",
"search_analyzer": "standard"
}
}
}
}
Insert records:
POST /my_index/my_type/_bulk
{ "index": { "_id": 1 }}
{ "name": "men's shaver" }
{ "index": { "_id": 2 }}
{ "name": "women's shaver" }
Query:
1. To search by exact phrase match --> "men's"
POST /my_index/my_type/_search
{
"query": {
"match": {
"name": "men's"
}
}
}
Above query returns "men's shaver" in the return result.
2. To search by Partial word match --> "en's"
POST /my_index/my_type/_search
{
"query": {
"match": {
"name": "en's"
}
}
}
Above query DOES NOT return anything.
I have also tried following query
POST /my_index/my_type/_search
{
"query": {
"wildcard": {
"name": {
"value": "%en's%"
}
}
}
}
Still not getting anything.
I figured it is because of "edge_ngram" type filter on Index which is not able to find "partial word/sbustring match".
I tried "n-gram" type filter as well but it is slowing down the search alot.
Please suggest me how to achieve both excact phrase match and partial phrase match using same index setting.
To search for partial field matches and exact matches, it will work better if you define the fields as "not analyzed" or as keywords (rather than text), then use a wildcard query.
See also this.
To use a wildcard query, append * on both ends of the string you are searching for:
POST /my_index/my_type/_search
{
"query": {
"wildcard": {
"name": {
"value": "*en's*"
}
}
}
}
To use with case insensitivity, use a custom analyzer with a lowercase filter and keyword tokenizer.
Custom Analyzer:
"custom_analyzer": {
"tokenizer": "keyword",
"filter": ["lowercase"]
}
Make the search string lowercase
If you get search string as AsD: change it to *asd*
The answer given by #BlackPOP will work, but it uses the wildcard approach, which is not preferred as it has a performance issue and if abused can create a huge domino effect (performance issue) in the Elastic cluster.
I have written a detailed blog on partial search/autocomplete covering the latest options available in Elasticsearch as of today (Dec 2020) with performance in mind. For more trade-off information please refer to this answer.
IMHO a better approach will be to use the customized n-gram tokenizer according to use-case, which will have already tokens needed for search term so it will be faster, although it will have a bigger index size, but you size is not that costly and speed will be better with more control on how exactly you want substring search to work.
Also size can be controlled if you are conservative in defining the min and max gram in tokenizer setting.
By searching with any string or substring Use:
query: {
or: [{
match_phrase_prefix: {
name: str
}
}, {
match_phrase_prefix: {
surname: str
}
}]
}
Happy coding with Elastic Search....

Using MERGE with properties via REST

According to the sample code at http://docs.neo4j.org/chunked/2.0.0-M03/rest-api-transactional.html I'm trying to use the MERGE statement.
But when I apply the following statement:
{
"statements": [
{
"statement": "MERGE (p:PERSON { identification }) ON CREATE p SET { properties } ON MATCH p SET { properties } RETURN p",
"parameters": {
"identification": {
"guid": "abc123xyz"
},
"properties": {
"lastName": "Doe",
"firstName": "John"
}
}
}
]
}
it gets back with the following 2 errors:
{ identification }
code: 42000,
status: STATEMENT_EXECUTION_ERROR,
message: Tried to set a property to a collection of mixed types. List(Map(guid -> abc123xyz))
SET { properties }
code: 42001,
status: STATEMENT_SYNTAX_ERROR",
message: =' expected butO' found\n\nThink we should have …
Can this not be done this way (yet) or am I missing something?
Thanks for your help
Daniel
It seems you've discovered a bug. I've reported the issue here:
https://github.com/neo4j/neo4j/issues/975
The issue is that MERGE needs to know the keys you will search on in advance. Passing a map of parameters hides this.
To achieve the same, list each key explicitly. If you still want to pass them all in a single map, you can probably do something like: MERGE (p:Person {name: {merge_map}.name, email: {merge_map}.email}).
Daniel,
I think you have to use SET differently, something like this:
MERGE (p:PERSON { identification })
ON CREATE p SET p={ properties }
ON MATCH p SET p={ properties }
RETURN p
But I'm not sure if that SET overrides all your properties. So it might be that you have to specify them one by one.
{
"statements": [
{
"statement": "MERGE (p:PERSON { guid : {guid} })
ON CREATE p SET p.lastName={lastName},p.firstName={ firstName }
ON MATCH p SET p.lastName={lastName},p.firstName={ firstName }
RETURN p",
"parameters": {
"guid": "abc123xyz",
"lastName": "Doe",
"firstName": "John"
}
}
]
}