Wiremock request matching for dynamic values - wiremock

The sample JSON I use for stub
{
"request": {
...
"bodyPatterns" : [ {
"equalToJson" : "{ \"id\": abc123 }",
"ignoreArrayOrder" : true,
"ignoreExtraElements" : true
} ]
...
},
here the id is a dynamic value, so in this case, how can I do the request matching in wire mock

You can use a wildcard to match any value of id:
"bodyPatterns" : [ {
"equalToJson" : "{ \"id\": \"${json-unit.any-string}\" }",
"ignoreArrayOrder" : true,
"ignoreExtraElements" : true
} ]

Related

Why I need to specify $switch default statement while it is optional?

I want to update the documents with a condition. I tried $cond, but it needs an expression for false case. And I don't want to update anything if it is false. Below is the sample of the document:
{
"_id" : ObjectId("5bc29e0d0fc2c40a9d628afe"),
"BasicInfo" : {
"RepNo" : "AE179",
"CompanyName" : "First Bancshares Inc",
"IRSNo" : "640862173",
"CIKNo" : "0000947559",
"Name" : "Ordinary Shares",
"Ticker" : "FBMS",
"CUSIP" : "318916103",
"ISIN" : "US3189161033",
"RIC" : "FBMS.O",
"SEDOL" : "2184300",
"DisplayRIC" : "FBMS.OQ",
"InstrumentPI" : "10552665",
"QuotePI" : "26300255",
"Exchange" : "NASDAQ"
},
"Annual" : {
"Date" : ISODate("2017-12-31T00:00:00.000Z"),
"INC" : {
"SIIB" : {
"Description" : "Interest Income, Bank",
"Value" : 66.06941
},
"STIE" : {
"Description" : "Total Interest Expense",
"Value" : 6.90925
},
"ENII" : {
"Description" : "Net Interest Income",
"Value" : 59.16016
Then, I tried to use $switch since the documentation said default statement is optional.
And I have written the following code:
db.getCollection('FinancialStatement').aggregate([
{"$unwind":"$Annual"},
{"$addFields":{"Annual.Price":
{"$switch":{
branches:[
{
case: {
"$and":[
{"$eq":["$_id", ObjectId("5bc29e0d0fc2c40a9d628afe")]},
{"$eq":["$Annual.Date", ISODate("2017-12-31 00:00:00.000Z")]}
]
},
then: 1000}
],
default: -2000
}
}
}
}
]
)
It basically add a new field called annual.price if objectID and date requirements are met. However, if I omitt the default statement, the program returns an error saying :
Assert: command failed: {
"ok" : 0,
"errmsg" : "$switch could not find a matching branch for an input, and no default was specified.",
"code" : 40066,
"codeName" : "Location40066"
}
From docs on usage of default
Optional. The path to take if no branch case expression evaluates to
true.
Although optional, if default is unspecified and no branch case
evaluates to true, $switch returns an error.
Use $$REMOVE in 3.6.
Something like
Using $cond
{"$addFields":{
"Annual.Price":{
"$cond":[
{
"$and":[
{"$eq":["$_id",ObjectId("5bc29e0d0fc2c40a9d628afe")]},
{"$eq":["$Annual.Date",ISODate("2017-12-31 00:00:00.000Z")]}
]
},
1000,
"$$REMOVE"
]
}
}}
Using $switch
{"$addFields":{
"Annual.Price":{
"$switch":{
"branches":[
{
"case":{
"$and":[
{"$eq":["$_id",ObjectId("5bc29e0d0fc2c40a9d628afe")]},
{"$eq":["$Annual.Date",ISODate("2017-12-31 00:00:00.000Z")]}
]
},
"then":1000
}
],
"default":"$$REMOVE"
}
}
}}

Can we use of Nested where clause in sails js Collection

I am trying below queries to get the output which has start_date greater than current date.
These in structure of my collection:
{
"_id" : ObjectId("5aeac6cd1b7e6f252832ca0e"),
"recruiter_id" : null,
"university_id" : null,
"type" : "quiz",
"name" : "Enter scheduled quiz without end date",
"description" : "Even after detailed market research, some products just don't work in the market. Here's a case study from the Coca-Cola range. ",
"quizpoll_image" : "story_7.jpeg",
"status" : "1",
"quizpoll_type" : "scheduled",
"duration" : {
"duration_type" : "Question wise",
"total_duration" : "1000"
},
"questions" : [
{
"question_id" : "5aeaa4021b7e6f00dc80c5c6"
},
{
"question_id" : "5aeaa59d1b7e6f00dc80c5d2"
}
],
"date_type" : {
"start_date" : ISODate("2018-05-01T00:00:00.000+0000")
},
"created_at" : ISODate("2018-05-01T00:00:00.000+0000"),
"updated_at" : ISODate("2018-04-26T07:58:17.795+0000")
}
This the query I am trying :
var isoCurrentDate = current_date.toISOString();
var quizScheduledData = await QuizListingCollection.find({
where: ({
'type':'quiz',
'status':'1',
'quizpoll_type':'scheduled',
'date_type' :{
'start_date':{
'>': isoCurrentDate
}
}
})
});
This is the error I get when I hit this api in postman
{
"cause": {
"name": "UsageError",
"code": "E_INVALID_CRITERIA",
"details": "Could not use the provided `where` clause. Could not filter by `date_type`: Unrecognized modifier (`start_date`) within provided constraint for `date_type`."
},
"isOperational": true,
"code": "E_INVALID_CRITERIA",
"details": "Could not use the provided `where` clause. Could not filter by `date_type`: Unrecognized modifier (`start_date`) within provided constraint for `date_type`."
}
{
where: {
'type':'quiz',
'status':'1',
'quizpoll_type':'scheduled',
'date_type.start_date': {
'>' : isoCurrentDate
}
}
}

Group multi addToSet requests in a single request

I have the following document :
{
"recordKey": "FOO",
"channels": [{
"id": "CH1",
"blocks": []
}, {
"id": "CH2",
"blocks": []
}]
}
In my current use case, I'm doing two requests with addToSet operator for adding new blocks for the channel CH1 or CH2 For example for the channel CH1, I'm doing this:
selector =
{
"$and" : [ {
"recordKey" : "FOO"
}, {
"channels.id" : "CH1"
} ]
}
addChunkRequest = "$addToSet" : {
"channels.$.blocks" : {
"$each" : [ {
"startime" : 101000000,
"blockType" : "DATA",
"fileLoc" : "/tmp/f1",
"nsamples" : 1000
}
query1 = db.collection.update(selector, update)
I'm doing the same think for the channel CH2. Now I want to group the two requests in one request. How can I achieve that ?
Well you cannot of course "update multiple array elements in the one operation", because that is just not presently allowed and a restriction of the positional $ operator.
What you "can" do however is use Bulk Operations to issue "both" operations in a "single request" to the server:
var data = [
{
"channel": "CH1",
"blocks": [{
"startime" : 101000000,
"blockType" : "DATA",
"fileLoc" : "/tmp/f1",
"nsamples" : 1000
}]
},
{
"channel": "CH2",
"blocks": [{
"startime" : 202000000,
"blockType" : "DATA",
"fileLoc" : "/tmp/f2",
"nsamples" : 2000
}]
}
]
var ops = data.map(d => ({
"updateOne": {
"filter": { "recordKey": "FOO", "channels.id": d.channel },
"update": {
"$addToSet": { "channels.$.blocks": { "$each": d.blocks } }
}
}
});
db.collection.bulkWrite(ops);
So it's still "two" operations and that cannot be avoided, however it's only "one" request and response from the server, and that actually helps you quite a lot.

MongoDB Conditional validation on arrays and embedded documents

I have a number of documents in my database where I am applying document validation. All of these documents may have embedded documents. I can apply simple validation along the lines of SQL non NULL checks (these are essentially enforcing the primary key constraints) but what I would like to do is apply some sort of conditional validation to the optional arrays and embedded documents. By example, lets say I have a document that looks like this:
{
"date": <<insertion date>>,
"name" : <<the portfolio name>>,
"assets" : << amount of money we have to trade with>>
}
Clearly I can put validation on this document to ensure that date name and assets all exist at insertion time. Lets say, however, that I'm managing a stock portfolio and the document can have future updates to show an array of stocks like this:
{
"date" : <<insertion date>>,
"name" : <<the portfolio name>>,
"assets" : << amount of money we have to trade with>>
"portfolio" : [
{ "stockName" : "IBM",
"pricePaid" : 155.39,
"sharesHeld" : 100
},
{ "stockName" : "Microsoft",
"pricePaid" : 57.22,
"sharesHeld" : 250
}
]
}
Is it possible to to apply a conditional validation to this array of sub documents? It's valid for the portfolio to not be there but if it is each document in the array must contain the three fields "stockName", "pricePaid" and "sharesHeld".
MongoShell
db.createCollection("collectionname",
{
validator: {
$or: [
{
"portfolio": {
$exists: false
}
},
{
$and: [
{
"portfolio": {
$exists: true
}
},
{
"portfolio.stockName": {
$type: "string",
$exists: true
}
},
{
"portfolio.pricePaid": {
$type: "double",
$exists: true
}
},
{
"portfolio.sharesHeld": {
$type: "double",
$exists: true
}
}
]
}
]
}
})
With this above validation in place you can insert documents with or without portfolio.
After executing the validator in shell, then you can insert data of following
db.collectionname.insert({
"_id" : ObjectId("58061aac8812662c9ae1b479"),
"date" : ISODate("2016-10-18T12:50:52.372Z"),
"name" : "B",
"assets" : 200
})
db.collectionname.insert({
"_id" : ObjectId("58061ab48812662c9ae1b47a"),
"date" : ISODate("2016-10-18T12:51:00.747Z"),
"name" : "A",
"assets" : 100,
"portfolio" : [
{
"stockName" : "Microsoft",
"pricePaid" : 57.22,
"sharesHeld" : 250
}
]
})
If we try to insert a document like this
db.collectionname.insert({
"date" : new Date(),
"name" : "A",
"assets" : 100,
"portfolio" : [
{ "stockName" : "IBM",
"sharesHeld" : 100
}
]
})
then we will get the below error message
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 121,
"errmsg" : "Document failed validation"
}
})
Using Mongoose
Yes it can be done, Based on your scenario you may need to initialize the parent and the child schema.
Shown below would be a sample of child(portfolio) schema in mongoose.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var portfolioSchema = new Schema({
"stockName" : { type : String, required : true },
"pricePaid" : { type : Number, required : true },
"sharesHeld" : { type : Number, required : true },
}
References:
http://mongoosejs.com/docs/guide.html
http://mongoosejs.com/docs/subdocs.html
Can I require an attribute to be set in a mongodb collection? (not null)
Hope it Helps!

Elasticsearch doesn't find value in range query

I launch following query:
GET archive-bp/_search
{
"query": {
"bool" : {
"filter" : [ {
"bool" : {
"should" : [ {
"terms" : {
"naDataOwnerCode" : [ "ACME-FinServ", "ACME-FinServ CA", "ACME-FinServ NY", "ACME-FinServ TX", "ACME-Shipping APA", "ACME-Shipping Eur", "ACME-Shipping LATAM", "ACME-Shipping ME", "ACME-TelCo-CN", "ACME-TelCo-ESAT", "ACME-TelCo-NL", "ACME-TelCo-PL", "ACME-TelCo-RO", "ACME-TelCo-SA", "ACME-TelCo-Treasury", "Default" ]
}
},
{
"bool" : {
"must_not" : {
"exists" : {
"field" : "naDataOwnerCode"
}
}
}
} ]
}
}, {
"range" : {
"bankCommunicationStatusDate" : {
"from" : "2006-02-27T06:45:47.000Z",
"to" : null,
"time_zone" : "+02:00",
"include_lower" : true,
"include_upper" : true
}
}
} ]
}
}
}
And I receive no results, but the field exists in my index.
When I strip off the data owner part, I still have no results. When I strip off the bankCommunicationDate, I get 10 results, so there is the problem.
The query of only the bankCommunicationDate:
GET archive-bp/_search
{
"query" :
{
"range" : {
"bankCommunicationStatusDate" : {
"from" : "2016-04-27T09:45:43.000Z",
"to" : "2026-04-27T09:45:43.000Z",
"time_zone" : "+02:00",
"include_lower" : true,
"include_upper" : true
}
}
}
}
The mapping of my index contains the following bankCommunicationStatusDate field:
"bankCommunicationStatusDate": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
}
And there are values for the field bankCommunicationStatusDate in elasticsearch:
"bankCommunicationStatusDate": "2016-04-27T09:45:43.000Z"
"bankCommunicationStatusDate": "2016-04-27T09:45:47.000Z"
What is wrong?
What version of Elastic Search do you use?
I guess the reason is that you should use "gte/lte" instead of "from/to/include_lower/include_upper".
According to documentation to version 0.90.4
https://www.elastic.co/guide/en/elasticsearch/reference/0.90/query-dsl-range-query.html
Deprecated in 0.90.4.
The from, to, include_lower and include_upper parameters have been deprecated in favour of gt,gte,lt,lte.
The strange thing is that I have tried your example on elastic search version 1.7 and it returns data!
I guess real depreciation took place much later - between 1.7 and maybe newer version you have.
BTW. You can isolate the problem even further using Sense plugin for Chrome and this code:
DELETE /test
PUT /test
{
"mappings": {
"myData" : {
"properties": {
"bankCommunicationStatusDate": {
"type": "date"
}
}
}
}
}
PUT test/myData/1
{
"bankCommunicationStatusDate":"2016-04-27T09:45:43.000Z"
}
PUT test/myData/2
{
"bankCommunicationStatusDate":"2016-04-27T09:45:47.000Z"
}
GET test/_search
{
"query" :
{
"range" : {
"bankCommunicationStatusDate" : {
"gte" : "2016-04-27T09:45:43.000Z",
"lte" : "2026-04-27T09:45:43.000Z"
}
}
}
}