Get json value based on dynamic key mapping for partial path - node.js

I am trying to get the values of a key in a json file, but there are several issues that I need to solve.
The key of the JSON is dynamic - I have another JSON in which I am given the path of the key inside the JSON.
For example, I have a json file that contains the following mapping:
{
"addressesPath":"personal.addresses"
}
This tells me that the value I am looking for is inside another key, called personal.
The JSON will look like this:
{
"username": "X1",
"id":"1X",
"type": "patron",
"group": "students",
"personal": {
"lastname": "lname",
"firstname": "fname",
"email": "test#test.test",
"phone": "1-111-111-1111",
"mobilePhone": "(111)111-1111",
"birthDate": "1979-01-23T00:00:00.000+0000",
"addresses":
{
"countryId": "US",
"addressLine1": "1111 Brannon Ford Suite 111",
"city": "Kettering",
"region": "MA",
"postalCode": "11111-1111",
"primaryAddress": true
}
}
}
So for example if the JSON is "user", what I want to get is user.personal.addresses
How can I translate "user.personal.addresses" to "users.+dynamic"?
I tried doing it just like that, but it doesn't seem to work with any type of string I extract from the mapping json file.
I have an issue because I don't know if the location I am getting is a single value or an array of values.
For example, the JSON could look like this:
{
"username": "X1",
"id":"1X",
"type": "patron",
"group": "students",
"personal": {
"lastname": "lname",
"firstname": "fname",
"email": "test#test.test",
"phone": "1-111-111-1111",
"mobilePhone": "(111)111-1111",
"birthDate": "1979-01-23T00:00:00.000+0000",
"addresses":[
{
"countryId": "US",
"addressLine1": "1111 Brannon Ford Suite 111",
"city": "Kettering",
"region": "MA",
"postalCode": "11111-1111",
"primaryAddress": true
}, {
"countryId": "US",
"addressLine1": "1112 Brannon Ford Suite 112",
"city": "Kettering",
"region": "IL",
"postalCode": "11112-1112",
"primaryAddress": false
}
]
}
}
Which means I need to determine the structure of the data I am going to get, whether it is an array or not.
Can I do this by checking if the result is a string or object? I know that arrays from JSON files are read as objects in node js.

You want something like that
With three examples
let object = {
"group": "students",
"personal": {
"addresses": {
"countryId": "US",
}
}
}
let test1 = checkObject(object, "personal.addresses")
console.log(test1);
let object2 = {
"test": {
"test_deep": [
{
"countryId": "US",
"addressLine1": "1111 Brannon Ford Suite 111"
},
{
"countryId": "US",
"addressLine1": "1112 Brannon Ford Suite 112",
}
]
}
}
let test2 = checkObject(object2, "test.test_deep")
console.log(test2);
let object3 = {
"test": {
"test_deep": "test"
}
}
let test3 = checkObject(object3, "test.test_deep")
console.log(test3);
function checkObject(object, addressesPath) {
let addres = addressesPath.split(".")
let item = object
for (let index = 0; index < addres.length; index++) {
if (typeof item[addres[index]] != 'undefined') {
item = item[addres[index]]
} else {
item = null
break
}
}
return {
type: typeof item,
is_array: Array.isArray(item),
data: item
}
}

Related

Using cond in mongo aggregate match expression

So i'm trying to query products based on the user specified filter. if the user specifies the size, for example XS, then i fetch all the products with 'XS' sizes, otherwise if the size isn't specified then i will fetch all the products without checking for their size. How can i do it with the mongo aggregation ?
here's my code.
1st: here's 2 products documents from my collection
[
{
"_id": "6124d16b1396d20aea617d75",
"username": "josh988",
"userpic": "josh.jpg",
"adresse": "545 Strawberry Lane Mokena, IL 60448",
"city": "Paris",
"country": "France",
"product": {
"_id": "62c064103a7b5160e957764c",
"images": [
"img1734116er1111111.jpeg"
],
"name": "White shirt",
"category": "Kids",
"subCategory": "Tshirts",
"size": "XS",
"price": 150
}
},
{
"_id": "6124d16b1396d20aea617d75",
"username": "laurel22",
"userpic": "laurel.jpg",
"adresse": "545 Strawberry Lane Mokena, IL 60448",
"city": "Lyon",
"country": "France",
"product": {
"_id": "62c064103a7b5160e957764c",
"images": [
"img1711656775696063.jpeg"
],
"name": "Black shirt",
"category": "Kids",
"subCategory": "Tshirts",
"size": "M",
"price": 250
}
},
]
to make the matter simple , my body api body request looks like this
{
"selectedCategory": "Kids",
"selectedSubCategory": "Tshirts",
// for e.g selectedSize could be XS
"selectedSize": null
}
So what i'd like to do is, if the user select a size then fetch the products with it otherwise fetch everything.
I tried this with mongo but didn't work
const searchResults = await user.aggregate([
{
$match: {
"product.category": `${req.body.selectedCategory}`,
"product.subCategory": `${req.body.selectedSubCategory}`,
$expr: {
$cond: {
// what should i do here ? or is there another way of achieving this
if: { $ne: [`${req.body.selectedSize}`, null] },
then: { product.size : req.body.selectedSize },
// and what should write here to fetch everything
else: { product.size: "" },
},
},
},
},
]);
You can generate the aggregation pipeline conditionally in nodejs itself. Like this:
let matchStage = {
$match: {
"product.category": `${req.body.selectedCategory}`,
"product.subCategory": `${req.body.selectedSubCategory}`,
}
};
if(req.body.selectedSize) {
matchStage = {
$match: {
...matchStage["$match"],
"product.size": request.body.selectedSize
}
};
}
const searchResults = await user.aggregate([matchStage]);

Best way to format the JSON content in Node.js application

I am working on an NODE JS based application. Trying to figure out any easy method to get my expected result. Had tried few ways, but after reframing the JSON content not able to add the key state.
My content JSON content is in this format
[
{
"item": {
"property1": "aa",
"property2": "22"
},
"state": {
"item": {
"state": "AS",
"country": "US",
"reason": "1"
}
},
"province": {
"item": {
"name": "AS",
"method": "table",
"conf": "3"
}
}
},
...
]
Requirement is to format state as below,
{
...
"state": [
{
"item": {
"state": "AS",
"country": "US",
"reason": "1"
}
}
],
...
}
I want to format the state content. The content is expected to be an array of JSON content. After formatting state, the orginal json content need to be modified with the new content of state. The issue faced here is after formatting not able to add the key state back to the orginal JSON content.Same is the expectation for province.
Requesting support from All...Thanks in Advance....
Below is the code i had written, but the expected result is not obtained.Can anyone help me in identifying were i have gone wrong
var testJson = JSON.parse(jsonData);
var tempFinal = [];
for(let i =0; i<testJson.length; i++) {
let itemData = {};
itemData.item = testJson[i].item;
tempFinal.push(itemData);
var state = [];
state.push( testJson[i].state);
let stateData = {};
stateData.state = state;
tempFinal.push(stateData);
var service = [];
service.push( testJson[i].service);
let serviceData = {};
serviceData.service = service;
tempFinal.push(serviceData);
}
The result obtained is
[
{
"item": {
"protocol": "tcp",
"portid": "22"
}
},
{
"state": [
{
"item": {
"state": "filtered",
"reason": "no-response",
"reason_ttl": "0"
}
}
]
},
{
"service": [
{
"item": {
"name": "ssh",
"method": "table",
"conf": "3"
}
}
]
}
]
Expected is
[
{
"item": {
"a": "a",
"a": "a"
},
"state": [
{
"item": {
"c": "b",
"e": "f",
"reason_ttl": "0"
}
}
],
"service": [
{
"item": {
"name": "q",
"method": "table",
"d": "e"
}
}
]
}
]
You can try this one
//jsonData is your original json data
jsonData.map((obj1=>{
//updating state data
obj1.state=[obj1.state];
}));
//finally print it.
console.log(jsonData);

Mongoose findByIdAndUpdate destroys missing fields

Developing a node.js api. I have mongo data that shows venues. It contains an address, for example....
"address": {
"street": "123 main st",
"city": "seomwhere",
"state": "FL",
"zip": "33222"
},
:
When I POST to the update endpoint and send the body like this it does update the address, but it REMOVES all the other fields that were there....
"address": {
"zip": "33222"
}
So, in the db, street, city, state are missing. Here's a piece of my code...
venue = await Venue.findByIdAndUpdate(req.params.id, req.body, {
new: true,
runValidators: true
});
Any ideas why?
Because address contains only single key in the body ("address": { "zip": "33222" }) it replaces the other values inside the address object with the blank ones in the database.
So to overcome the issue you have to use . notation with the address object. Like
venue = await Venue.findByIdAndUpdate(
req.params.id,
{ $set: { "address.zip": "33222" },
{ new: true, runValidators: true }
)
But as you cannot identify which keys inside the address object will be updated and also for the root level
const object = req.body
for (var key in req.body.address) {
object[`address.${key}`] = object.address[key]
}
delete object.address
venue = await Venue.findByIdAndUpdate(
req.params.id,
{ $set: object },
{ new: true, runValidators: true }
)
You are overwriting existing address fields when not specified in the request body.
You need to only update the fields in the request body:
const fields = {};
Object.keys(req.body.address).forEach(key => {
fields[`address.${key}`] = req.body.address[key];
});
const venue = await Venue.findByIdAndUpdate(req.params.id, fields, {
new: true,
runValidators: true
});
Let's say we have this venue document:
{
"_id": "5e047d4e10be4f0da4c61703",
"name": "Venue 1",
"address": {
"street": "123 main st",
"city": "seomwhere",
"state": "FL",
"zip": "33222"
},
"__v": 0
}
When you use a requset body like this:
{
"address": {
"zip": "33333"
}
}
The response will be:
{
"address": {
"street": "123 main st",
"city": "seomwhere",
"state": "FL",
"zip": "33333"
},
"_id": "5e047d4e10be4f0da4c61703",
"name": "Venue 1",
"__v": 0
}
And when we want to update like this:
{
"address": {
"state": "NY",
"zip": "44444"
}
}
The response will be:
{
"address": {
"street": "123 main st",
"city": "seomwhere",
"state": "NY",
"zip": "44444"
},
"_id": "5e047d4e10be4f0da4c61703",
"name": "Venue 1",
"__v": 0
}

Restructure json based on actual and expected data

I want to restructure json based on original json data and the expected json data.
If you look closely in the original json data I have country outside of the Male/Female attributes. I would want the country module to be inside the Male/ Female attribute based on the orientation attribute inside the country module. So in the afterdata I would have 1 country module in Male attribute(since there is 1 male record) and 2 country module in Female attribute(since there are 2 female records).
Original json data looks like this:
{
"Implementations": [
{
"Male": {
"Gender": "Male"
},
"Female": {
"Gender": "Female"
},
"Country": [
{
"Orientation": "Male",
"Name": ABCD
},
{
"Orientation": "Female",
"Name": EFGH
},
{
"Orientation": "Female",
"Name": IJKL
}
],
"State": [
{
"Address": "XYZ Street",
"ZipCode": "US"
}
]
}
]
}
Expected json data:
{
"Implementations": [
{
"Male": {
"Gender": "Male"
"Country": [
{
"Orientation": "Male",
"Name": ABCD
}
],
"State": [
{
"Address": "XYZ Street",
"ZipCode": "US"
}
]
},
"Female": {
"Gender": "Female"
"Country": [
{
"Orientation": "Female",
"Name": EFGH
},
{
"Orientation": "Female",
"Name": IJKL
}
],
"State": [
{
"Address": "XYZ Street",
"ZipCode": "US"
}
]
}
}
]
}
Program:
var Implementations = {
"Implementations": [
{
"Male": {
"Gender": "Male"
},
"Female": {
"Gender": "Female"
},
"Country": [
{
"Orientation": "Male",
"Name": ABCD
},
{
"Orientation": "Female",
"Name": EFGH
},
{
"Orientation": "Female",
"Name": IJKL
}
],
"State": [
{
"Address": "XYZ Street",
"ZipCode": "US"
}
]
}
]
}
var output = [];
for (k in Implementations.Implementations.Male) {
var temp = [];
for (j in Implementations.Implementations.Male[k]) {
temp.push({
Country: j
});
}
output.push({
"Implementations": k,
Country: temp
});
}
console.log(output);
Thank you in advance!
Your program does not work because Implementations.Implementations is an array, it doesn't have field named Male.
Here is a working code snippet:
//Original JSON data in question.
var Implementations = {
"Implementations": [
{
"Male": {
"Gender": "Male"
},
"Female": {
"Gender": "Female"
},
"Country": [
{
"Orientation": "Male",
"Name": ABCD
},
{
"Orientation": "Female",
"Name": EFGH
},
{
"Orientation": "Female",
"Name": IJKL
}
],
"State": [
{
"Address": "XYZ Street",
"ZipCode": "US"
}
]
}
]
}
// Program that make the conversion
var finalResult = [];
for (var i=0; i<Implementations.Implementations.length; i++) {
var currentImplementation = Implementations.Implementations[i];
var targetObj = {
"Male": {
"Gender": "Male",
"Country": [],
"State": currentImplementation.State
},
"Female": {
"Gender": "Female",
"Country": [],
"State": currentImplementation.State
}
};
for (var j=0; j<currentImplementation.Country.length; j++) {
var currentCountry = currentImplementation.Country[j];
if (currentCountry.Orientation === 'Male') {
targetObj.Male.Country.push(currentCountry);
} else if (currentCountry.Orientation === 'Female') {
targetObj.Female.Country.push(currentCountry);
}
}
finalResult.push(targetObj);
}
console.log(JSON.stringify(finalResult));

CouchDB's Linked Documents in a View

I'm having a hard time getting my head around CouchDB's linked documents feature.
I have two types of data being stored in a single CouchDB database:
{
"id":"1",
"type": "track",
"title": "Bohemian Rhapsody"
}
{
"id":"2",
"type": "artist",
"name": "Queen",
"tracks": ["1"]
}
I'm under the impression that I can write a view like the one below and get the following documents emited:
{
"id":"2",
"type": "artist",
"name": "Queen",
"tracks": [
{
"id":"1",
"type": "track",
"title": "Bohemian Rhapsody"
}
]
}
I've been trying this view, but it's not working the way I'm expecting:
function(doc) {
if(doc.type == 'artist') {
var tracks = [];
for(var i = 0; i < doc.tracks.length; i++) {
tracks.push({_id:doc.tracks[i]});
}
newdoc = eval(uneval(doc));
newdoc.tracks = tracks;
emit(doc._id,newdoc);
}
}
example here: http://jphastings.iriscouch.com/_utils/database.html?music/_design/test/_view/linked
This isn't returning what I'd hope - do you have any suggestions? Thanks
Okay I finally understand what you are trying to do.Yes this is possible.Here is how.
You have 2 documents
{
"_id":"anyvalue",
"type": "track",
"title": "Bohemian Rhapsody"
}
{
"_id":"2",
"type": "artist",
"name": "Queen",
"tracks": ["anyvalue"]
}
What you were doing wrong was not having quotes around the value of tracks(the item in the array).
2)The reference id must be _id for this to work.The difference is worth noting since you can have id field but only _id are used to identify documents.
For the result you want this view would suffice
function(doc) {
if (doc.type === 'artist') {
for (var i in doc.tracks) {
var id = doc.tracks[i];
emit(id, { _id: id });
}
}
}
What you want to be doing is use an emit function inside the for loop to emit the id field of the 'track' of every artist.
Then you want to query couch db view with the include_docs=true parameter.Here is the final result for the database that you created on iris couch.
http://jphastings.iriscouch.com/music/_design/test/_view/nested?reduce=false&include_docs=true
{
"total_rows": 3,
"offset": 0,
"rows": [
{
"id": "0b86008d8490abf0b7e4f15f0c6a50a7",
"key": "0b86008d8490abf0b7e4f15f0c6a463b",
"value": {
"_id": "0b86008d8490abf0b7e4f15f0c6a463b"
},
"doc": {
"_id": "0b86008d8490abf0b7e4f15f0c6a463b",
"_rev": "3-7e4ba3bfedd29a07898125c09dd7262e",
"type": "track",
"title": "Boheniam Rhapsody"
}
},
{
"id": "0b86008d8490abf0b7e4f15f0c6a50a7",
"key": "0b86008d8490abf0b7e4f15f0c6a5ae2",
"value": {
"_id": "0b86008d8490abf0b7e4f15f0c6a5ae2"
},
"doc": {
"_id": "0b86008d8490abf0b7e4f15f0c6a5ae2",
"_rev": "2-b3989dd37ef4d8ed58516835900b549e",
"type": "track",
"title": "Another one bites the dust"
}
},
{
"id": "0b86008d8490abf0b7e4f15f0c6a695e",
"key": "0b86008d8490abf0b7e4f15f0c6a6353",
"value": {
"_id": "0b86008d8490abf0b7e4f15f0c6a6353"
},
"doc": {
"_id": "0b86008d8490abf0b7e4f15f0c6a6353",
"_rev": "2-0383f18c198b813943615d2bf59c212a",
"type": "track",
"title": "Stripper Vicar"
}
}
]
}
Jason explains it wonderfully in this post
Best way to do one-to-many "JOIN" in CouchDB
this link is also helpful for entity relationships in couch db
http://wiki.apache.org/couchdb/EntityRelationship

Resources