My input looks like below
{
"honda" : {
"accord" : [ "30", "20" ],
"plus" : [ "20", "10", "" ]
},
"tesla" : {
"modelY" : [ "50", "20", "" ],
"modelX" : [ "20", "" ]
}
}
I want to write a spec to get only the first value in the array for each model. This is dynamic data and may vary depending on the query. The output must look something like this. I have tried an no luck with the dynamic key.
{
"honda" : {
"accord" : "30",
"plus" : "20"
},
"tesla" : {
"modelY" : "50",
"modelX" : "20"
}
}
Check this spec,
[
{
"operation": "shift",
"spec": {
"*": {
"*": {
"0": "&2.&1"
}
}
}
}
]
Related
I need to pass the following array as query paramsin wiremock.Is there any possibility of doing that?
"Person": [
{
"name": "AAA",
"age": "20"
},
{
"name": "BBB",
"age": "26"
}
]
I have tried
"bodyPatterns" : [
{
"matchesJsonPath" : "$[?(#.Person.size() >= 2)]"
}
]
and
"bodyPatterns" : [
{
"matchesJsonPath" : "$.Person.name"
},
{
"matchesJsonPath" : "$.Person.age"
}
]
I am trying to convert a JSON to different format using JOLT (using NiFi JoltTransformJson processor). For single JSON record, the JOLT am using is working fine in JOLT app demo whereas if i execute with multiple JSON records then I am not getting expected output in JOLT app demo. Could anyone correct me what additional changes I need to do in JOLT spec to handle multiple JSON records.
sample input json
[
{
"pool": {
"field": [
{
"name": "BillingDay",
"value": "12"
},
{
"name": "Custom1",
"value": "POOL_BASE_PLAN_3GB"
}
]
},
"usage": {
"version": "3",
"quota": {
"name": "POOL_TOP_UP_1GB_2",
"cid": "5764888998010953848"
}
},
"state": {
"version": "1",
"property": [
{
"name": "SMS_RO_TOP",
"value": "1"
},
{
"name": "BillingTimeStamp",
"value": "2020-06-12T01:00:05"
},
{
"name": "timereset",
"value": "2020-01-12T00:35:53"
}
]
}
},
{
"pool": {
"field": [
{
"name": "PoolID",
"value": "111100110000003505209"
},
{
"name": "BillingDay",
"value": "9"
}
]
},
"usage": {
"version": "3"
},
"state": {
"version": "1",
"property": [
{
"name": "BillingTimeStamp",
"value": "2020-06-09T01:00:05"
},
{
"name": "timereset",
"value": "2019-03-20T17:10:38"
}
]
}
}
]
JOLT using:
[
{
"operation": "modify-default-beta",
"spec": {
"state": {
"property": {
"name": "NOTAVAILABLE"
}
},
"usage": {
"quota": {
"name": "NOTAVAILABLE"
}
}
}
},
{
"operation": "shift",
"spec": {
"pool": {
"field": {
"*": {
"value": "pool_item.#(1,name)"
}
}
},
// remaining elements print as it is
"*": "&"
}
}
]
Expected output JSON:
[
{
"pool_item" : {
"BillingDay" : "12",
"Custom1" : "POOL_BASE_PLAN_3GB"
},
"usage" : {
"version" : "3",
"quota" : {
"name" : "POOL_TOP_UP_1GB_2",
"cid" : "5764888998010953848"
}
},
"state" : {
"version" : "1",
"property" : [ {
"name" : "SMS_RO_TOP",
"value" : "1"
}, {
"name" : "BillingTimeStamp",
"value" : "2020-06-12T01:00:05"
}, {
"name" : "timereset",
"value" : "2020-01-12T00:35:53"
} ]
}
},
{
"pool_item" : {
"BillingDay" : "9",
"PoolID" : "111100110000003505209"
},
"usage" : {
"version" : "3",
"quota" : {
"name" : "NOTAVAILABLE"
}
},
"state" : {
"version" : "1",
"property" : [ {
"name" : "SMS_RO_TOP",
"value" : "1"
}, {
"name" : "BillingTimeStamp",
"value" : "2020-06-12T01:00:05"
}, {
"name" : "timereset",
"value" : "2020-01-12T00:35:53"
} ]
}
}
]
This below jolt shift specification will work for your multiple json's in input array.
[
{
"operation": "shift",
"spec": {
"*": {
"pool": {
"field": {
"*": {
"value": "[&4].pool_item.#(1,name)"
}
}
},
"usage": "[&1].usage",
"state": "[&1].state"
}
}
}
]
Following is my query does exactly match with my document but still not getting output.Don't know why. Following is the document as well.
db.getCollection("analytics").find(
{
"$and" : [
{
"archive" : false
},
{
"platform" : "WEB"
},
{
"vendorId" : "3c7adbfe-14d7-4b26-9134-7e05d56573cc"
},
{
"createdAt" : {
"$gte" : 1578268800000.0
}
},
{
"createdAt" : {
"$lte" : 1580860800000.0
}
},
{
"$and" : [
{
"data.mobile" : "123"
},
{
"page" : "Loan Application"
},
{
"event" : "click"
}
]
},
{
"$and" : [
{
"data.aadharNumber" : "123"
},
{
"page" : "Personal Information"
},
{
"event" : "click"
}
]
},
{
"$and" : [
{
"data.totalExp" : "5"
},
{
"page" : "Professional Information"
},
{
"event" : "click"
}
]
}
]
}
);
Documents :
[
{
"page": "Loan Application",
"event": "click",
"loggedIn": true,
"vendorId": "3c7adbfe-14d7-4b26-9134-7e05d56573cc",
"data": {
"first": "Praveen",
"mobile": "1234"
},
"platform": "WEB"
},
{
"page": "Personal Information",
"event": "click",
"loggedIn": true,
"vendorId": "3c7adbfe-14d7-4b26-9134-7e05d56573cc",
"data": {
"panNumber": "123",
"aadharNumber": "123"
},
"platform": "WEB"
},
{
"page": "Professional Information",
"event": "click",
"loggedIn": true,
"vendorId": "3c7adbfe-14d7-4b26-9134-7e05d56573cc",
"data": {
"totalExp": "5"
},
"platform": "WEB"
}
]
There are a lot of issues going on with your query, you can try below query to return all documents :
db.getCollection("analytics").find({
$expr: {
$and: [
{
$eq: [
"$platform",
"WEB"
]
},
{
$eq: [
"$vendorId",
"3c7adbfe-14d7-4b26-9134-7e05d56573cc"
]
},
{
$or: [
{
"$and": [
{
"data": {
"mobile": "123"
}
},
{
"page": "Loan Application"
},
{
"event": "click"
}
]
},
{
"$and": [
{
"data": {
"aadharNumber": "123"
}
},
{
"page": "Personal Information"
},
{
"event": "click"
}
]
},
{
"$and": [
{
"data": {
"totalExp": "5"
}
},
{
"page": "Professional Information"
},
{
"event": "click"
}
]
}
]
}
]
}
})
Test : MongoDB-Playground
I try to flatten some JSON arrays using Jolt. I found how to do it on the first level, but I need to do it "recursively".
About the input:
the array I want to flatten are name "objects"
the inner objects all contain a "name" attribute but the others attributes are not common
Here is a simple sample:
{
"objects": [
{
"name": "first",
"type": "FIRST",
"1st_attr": 0
},
{
"name": "second",
"type": "SECOND",
"2nd_attr": 0
}
],
"sub": {
"objects": [
{
"name": "third",
"type": "THIRD",
"3rd_attr": 0
}
]
}
}
Here is the output I want:
{
"first" : {
"1st_attr" : 0,
"name" : "first",
"type" : "FIRST"
},
"second" : {
"2nd_attr" : 0,
"name" : "second",
"type" : "SECOND"
},
"sub" : {
"third" : {
"3rd_attr" : 0,
"name" : "third",
"type" : "THIRD"
}
}
}
The spec I have flatten the first level, but I would like to have it flatten every level (meanining, not just the second ;)...):
[
{
"operation": "shift",
"spec": {
"objects": {
"*": {
"#": "#(1,name)"
}
},
"*": "&0"
}
}
]
Thanks for your help
With Jolt you have to know where in your input the "object" arrays are. There isn't a way to "just find and flatten all the arrays, no matter where they are in the input doc".
Spec for the input and output you provided :
[
{
"operation": "shift",
"spec": {
"objects": {
"*": "#(0,name)"
},
"sub": {
"objects": {
"*": "&2.#(0,name)"
}
}
}
}
]
Edit: added &2. to have sub.third instead of just third
I know you can count how many elements are in a collection with
collection.find().count().
However, I was wondering how can I count a certain element inside the item inside the collection. For example I have four images inside a Documents like this:
"Documents":{
"1":"image.png",
"2":"Test.jpg",
"3":"Next.png"
}
I was wondering how I can count all the items in Documents? I have tried a few things but none of them are working. Can anyone help?
Example data:
{
"name": "Oran",
"username": "Oran.Hammes",
"avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/brandonflatsoda/128.jpg",
"email": "xxxxxx#hotmail.com",
"dob": "1953-03-21T17:40:17.020Z",
"phone": "364-846-1607",
"address": {
"street": "Schultz Stream",
"suite": "Suite 618",
"city": "North Muriel mouth",
"zipcode": "06447-1081",
"geo": {
"lat": "57.1844",
"lng": "-56.8890"
}
},
"website": "misty.net",
"company": {
"name": "Hettinger, Reilly and Stracke",
"catchPhrase": "Multi-tiered system-worthy database",
"bs": "best-of-breed evolve e-markets"
},
"Documents": [
{
"id": "1",
"name": "image.png",
},
{
"id": "2",
"name": "Test.jpg",
},
{
"id": "3",
"name": "Next.png"
}
]
}
After this comment I changed my document's structure and it looks like this:
{
"_id" : ObjectId("568703d08981f193cf343698"),
"name" : "Oran",
"username" : "Oran.Hammes",
"email" : "xxxxxxx#hotmail.com",
"dob" : "1953-03-21T17:40:17.020Z",
"phone" : "364-846-1607",
"company" : {
"name" : "Hettinger, Reilly and Stracke",
"catchPhrase" : "Multi-tiered system-worthy database",
"bs" : "best-of-breed evolve e-markets"
},
"Documents" : [
{
"id" : "1",
"name" : "image.png"
},
{
"id" : "2",
"name" : "Test.jpg"
},
{
"id" : "3",
"name" : "Next.png"
}
]
}
Generally speaking it's not a good idea to have dynamic keys in your documents. Your best bet in situation like this is mapReduce
var map = function() {
emit(this._id, Object.keys(this.Documents).length);
};
var reduce = function(key, values) {};
db.collection.mapReduce(map, reduce, { "out": { "inline": 1 } } )
Which yields:
{
"results" : [
{
"_id" : ObjectId("5686e2a98981f193cf343697"),
"value" : 3
}
],
"timeMillis" : 697,
"counts" : {
"input" : 1,
"emit" : 1,
"reduce" : 0,
"output" : 1
},
"ok" : 1
}
Definitely the best thing to do is to change your documents structure and make Documents an array of sub-documents so that the Documents field value looks like this:
"Documents": [
{
"id": "1",
"name": "image.png",
},
{
"id": "2",
"name": "Test.jpg",
},
{
"id": "3",
"name": "Next.png"
}
]
and use the .aggregate() method to $project your documents and return the number of elements in the "Documents" array using the $size operator
db.collections.aggregate([
{ "$project": { "count": { "$size": "$Documents" } } }
] )