Nested object iteration - object

Fighting with this one for a while now...
I'm trying to modify each image object by adding more keys-values and changing some values.
As the keys are not having the same names, I need to identify the images by .hasOwnProperty('formats')
The object can be even more nested not only with key-values pairs but with arrays as well (this is where it gets complicated)
const object = {
name: "help",
mainImage: {
name: "picture1",
formats: {
small: {
name: "small_picture1",
},
medium: {
name: "medium_picture1",
},
large: {
name: "large_picture1",
},
},
},
carousel: [
{
name: "picture2",
formats: {
small: {
name: "small_picture2",
},
medium: {
name: "medium_picture2",
},
large: {
name: "large_picture2",
},
},
},
{
name: "picture3",
formats: {
small: {
name: "small_picture3",
},
medium: {
name: "medium_picture3",
},
large: {
name: "large_picture3",
},
},
},
],
nestedPage: {
name: "moreHelp",
mainImage: {
name: "picture4",
formats: {
small: {
name: "small_picture4",
},
medium: {
name: "medium_picture4",
},
large: {
name: "large_picture4",
},
},
},
carousel: [
{
name: "picture5",
formats: {
small: {
name: "small_picture5",
},
medium: {
name: "medium_picture5",
},
large: {
name: "large_picture5",
},
},
},
{
name: "picture5",
formats: {
small: {
name: "small_picture5",
},
medium: {
name: "medium_picture5",
},
large: {
name: "large_picture5",
},
},
},
],
},
};
This is what I tried, but it only goes to a certain level.
const customSanitizer = (entity) => {
const isObject = (value) => {
return !!(value && typeof value === "object" && !Array.isArray(value));
};
if (isObject(entity)) {
Object.entries(entity).forEach(([key, value]) => {
if (isObject(entity[key])) {
if (value.hasOwnProperty("formats")) {
entity[key] = formatImageObject(value);
} else {
customSanitizer(entity[key]);
}
} else {
customSanitizer(entity[key]);
}
});
}
if (Array.isArray(entity)) {
entity.forEach((node) => {
customSanitizer(node);
});
}
}

Related

How to aggregate and filter mongodb collections correctly in node (mongoose)?

I have a collection of motorcycles in my MongoDB database. Each motorcycle (collection) has an array of units and each unit has an array of parts with the name and SKU number. I'm trying to fetch only those units which contain given SKU number (in this example PT00002).
I tried to use aggregation, project and filter, but every time I get empty array of units:
let responseData = await Model.aggregate([
{
$match: {
'units.parts.SKU': sku,
}
},
{
$project: {
'units': {
$filter: {
input: '$units',
as: 'unit',
cond: {
$eq: [
'$$unit.parts.SKU', sku
]
}
}
}
}
}
]);
Documents look like this:
{
_id: ObjectId('6351183b841ef5ca0e090482'),
name: 'Yamaha Tenere 2022',
units: [
{
name: 'Front wheel',
parts: [
{
SKU: 'PT00001',
name: 'Bolt m7'
},
{
SKU: 'PT00002',
name: 'Oring'
},
]
},
{
name: 'Rear wheel',
parts: [
{
SKU: 'PT00003',
name: 'Bolt m7'
},
{
SKU: 'PT00002',
name: 'Oring'
},
]
}
]
}
and
{
_id: ObjectId('6351183b841ef5ca0e090483'),
name: 'Yamaha Tenere 2021',
units: [
{
name: 'Exhaust system',
parts: [
{
SKU: 'PT00012',
name: 'Screw torx'
},
{
SKU: 'PT00002',
name: 'Oring'
},
]
},
{
name: 'Suspension',
parts: [
{
SKU: 'GGG02',
name: 'Front fork'
},
{
SKU: 'GGG02',
name: 'Rear fork'
},
]
}
]
}
Expected output (for SKU PT00002 ) should be like this (no "Suspension unit" in array):
{
_id: ObjectId('6351183b841ef5ca0e090482'),
name: 'Yamaha Tenere 2022',
units: [
{
name: 'Front wheel',
parts: [
{
SKU: 'PT00001',
name: 'Bolt m7'
},
{
SKU: 'PT00002',
name: 'Oring'
},
]
},
{
name: 'Rear wheel',
parts: [
{
SKU: 'PT00003',
name: 'Bolt m7'
},
{
SKU: 'PT00002',
name: 'Oring'
},
]
}
]
},
{
_id: ObjectId('6351183b841ef5ca0e090483'),
name: 'Yamaha Tenere 2021',
units: [
{
name: 'Exhaust system',
parts: [
{
SKU: 'PT00012',
name: 'Screw torx'
},
{
SKU: 'PT00002',
name: 'Oring'
},
]
},
]
}
Looks like I had small error with my aggregate query. The one below works:
let responseData = await Model.aggregate([
{
$match: {
'units.parts.SKU': sku,
}
},
{
$project: {
'name': 1,
'year': 1,
'code': 1,
'category': 1,
'units': {
$filter: {
input: '$units',
as: 'unit',
cond: {
$in: [
sku, '$$unit.parts.SKU'
],
}
}
}
}
}
]);

TypeError: Cannot read properties of undefined (reading 'path')

I'm attempting to generate NFTs using this code but keep getting cannot read properties of undefined reading path, if anyone knows of a fix please write back. I am very new to this whole process and do not know what i should be looking at, i've been following the steps exactly as stated in the youtube video i was watching and this problem was not happening with the person in the video.
const path = require("path");
const isLocal = typeof process.pkg === "undefined";
const basePath = isLocal ? process.cwd() : path.dirname(process.execPath);
const { MODE } = require(path.join(basePath, "constants/blend_mode.js"));
const { NETWORK } = require(path.join(basePath, "constants/network.js"));
const network = NETWORK.sol;
// General metadata for Ethereum
const namePrefix = "CHUMPSNFT";
const description = "2,222 Chumps storming Solana Beaches";
const baseUri = "ipfs://NewUriToReplace";
const solanaMetadata = {
symbol: "CHUMP",
seller_fee_basis_points: 700, // Define how much % you want from secondary market sales 1000 = 10%
external_url: "https://www.loosebucks.net",
creators: [
{
address: "HXzaa6foNqG3w7XaVykaH6jWAFpNkCfJeDyhXsih2U93",
share: 100,
},
],
};
// If you have selected Solana then the collection starts from 0 automatically
const layerConfigurations = [
{
growEditionSizeTo: 163,
layersOrder: [
{ name: "Background" },
{ name: "Body Color" },
{ name: "Top" },
{ name: "Accessories" },
{ name: "Face" },
{ name: "Head" },
{ name: "Eyes" },
],
},
{
growEditionSizeTo: 326,
layersOrder: [
{ name: "Background" },
{ name: "Body Color" },
{ name: "Face" },
{ name: "Head" },
{ name: "Eyes" },
],
},
{
growEditionSizeTo: 489,
layersOrder: [
{ name: "Background" },
{ name: "Body Color" },
{ name: "Top" },
{ name: "Accessories" },
{ name: "Eyes" },
],
},
{
growEditionSizeTo: 652,
layersOrder: [
{ name: "Background" },
{ name: "Body Color" },
{ name: "Accessories" },
{ name: "Face" },
{ name: "Head" },
{ name: "Eyes" },
],
},
{
growEditionSizeTo: 815,
layersOrder: [
{ name: "Background" },
{ name: "Body Color" },
{ name: "Accessories" },
{ name: "Head" },
{ name: "Eyes" },
],
},
{
growEditionSizeTo: 978,
layersOrder: [
{ name: "Background1" },
{ name: "Body Color1" },
{ name: "Top1" },
{ name: "Accessories1" },
{ name: "Face1" },
{ name: "Head1" },
{ name: "Eyes1" },
],
},
{
growEditionSizeTo: 1141,
layersOrder: [
{ name: "Background" },
{ name: "Body Color" },
{ name: "Top" },
{ name: "Eyes" },
],
},
{
growEditionSizeTo: 1304,
layersOrder: [
{ name: "Background" },
{ name: "Body Color" },
{ name: "Accessories" },
{ name: "Face" },
{ name: "Eyes" },
],
},
{
growEditionSizeTo: 1467,
layersOrder: [
{ name: "Background" },
{ name: "Body Color" },
{ name: "Eyes" },
],
},
{
growEditionSizeTo: 1630,
layersOrder: [
{ name: "Background" },
{ name: "Body Color" },
{ name: "Face" },
{ name: "Eyes" },
],
},
{
growEditionSizeTo: 1793,
layersOrder: [
{ name: "Background" },
{ name: "Body Color" },
{ name: "Top" },
{ name: "Head" },
{ name: "Eyes" },
],
},
{
growEditionSizeTo: 1956,
layersOrder: [
{ name: "Background" },
{ name: "Body Color" },
{ name: "Accessories" },
{ name: "Eyes" },
],
},
{
growEditionSizeTo: 2119,
layersOrder: [
{ name: "Background1" },
{ name: "Body Color1" },
{ name: "Accessories1" },
{ name: "Eyes1" },
],
},
{
growEditionSizeTo: 2282,
layersOrder: [
{ name: "Background1" },
{ name: "Body Color1" },
{ name: "Top1" },
{ name: "Accessories1" },
{ name: "Face1" },
{ name: "Eyes1" },
],
},
];
const shuffleLayerConfigurations = false;
const debugLogs = false;
const format = {
width: 512,
height: 512,
};
const text = {
only: false,
color: "#ffffff",
size: 20,
xGap: 40,
yGap: 40,
align: "left",
baseline: "top",
weight: "regular",
family: "Courier",
spacer: " => ",
};
const pixelFormat = {
ratio: 2 / 128,
};
const background = {
generate: true,
brightness: "80%",
static: false,
default: "#000000",
};
const extraMetadata = {};
const rarityDelimiter = "#";
const uniqueDnaTorrance = 10000;
const preview = {
thumbPerRow: 5,
thumbWidth: 50,
imageRatio: format.width / format.height,
imageName: "preview.png",
};
module.exports = {
format,
baseUri,
description,
background,
uniqueDnaTorrance,
layerConfigurations,
rarityDelimiter,
preview,
shuffleLayerConfigurations,
debugLogs,
extraMetadata,
pixelFormat,
text,
namePrefix,
network,
solanaMetadata,
}; ```
Make sure the naming of your assets in layers is correct(only use underscores, a to z and hashtag).
Also no folder should be empty
Best of luck
Are you using anything other than Underscores letters a to z and hashtags in the naming of your images in the layers folders. If so it's probably the reason why your getting an error.
I had the same problem.
It turned out that a layers folder was empty, I was saving the images in another path and I thought it was the same one.
In the layers folders check if you have images saved or if the path is what you think.

Displaying specific id from json file with reactjs

How could I display data from a json file using reactjs.
I would like to display a specific value on my website using a json file.
Using this example json file.
const data = [
{
items: {
item: [
{
id: "0001",
type: "donut",
name: "Cake",
ppu: 0.55,
batters: {
batter: [
{
id: "377",
type: "Regular",
},
{
id: "609",
type: "Chocolate",
},
{
id: "788",
type: "Blueberry",
},
{
id: "809",
type: "Devil's Food",
},
],
},
topping: [
{
id: "5001",
type: "None",
},
{
id: "5002",
type: "Glazed",
},
{
id: "5005",
type: "Sugar",
},
{
id: "5007",
type: "Powdered Sugar",
},
{
id: "5006",
type: "Chocolate with Sprinkles",
},
{
id: "5003",
type: "Chocolate",
},
{
id: "5004",
type: "Maple",
},
],
},
],
},
},
];
How could I access for example items.item.batters.batter for id 609 and display the type in this case "Chocolate" using reactjs without using something like this:
batters.batter[1].type
and instead displaying it for the specific id (609)?
If you need to find a specific object, that has a specific value in a list of objects, you can do it as such:
const [batter, setBatter] = useState([
{
id: "377",
type: "Regular"
},
{
id: "609",
type: "Chocolate"
},
{
id: "788",
type: "Blueberry"
},
{
id: "809",
type: "Devil's Food"
}
]);
const [results, setResults] = useState([]);
const searchInList = () => {
let _results = [];
let toSearch = 609;
for (var i = 0; i < batter.length; i++) {
for (key in batter[i]) {
if (batter[i][key].indexOf(toSearch) != -1) {
_results.push(batter[i]);
}
}
}
};
setResults(_results);
useEffect(() => {
searchInList();
}, [batter]);
You can read more about this here: JS search in object values

how to pass param while getting billing data azure function

For getting the azure subscription billing data I am passing params it's not apply
const axios = require('axios');
let usage = [];
function getUsage(subscriptionId, accessToken) {
const url = `https://management.azure.com/subscriptions/${subscriptionId}/providers/Microsoft.Consumption/usageDetails?api-version=2019-01-01`
const options = {
headers: {
Authorization: `Bearer ${accessToken}`
}
}
// I am trying to pass data for filtering
const params ={
type: "Usage",
timeframe: "MonthToDate",
dataset: {
granularity: "None",
aggregation: {
totalCost: {
name: "PreTaxCost",
function: "Sum"
}
},
grouping: [
{
type: "Dimension",
name: "MeterCategory"
},
{
type: "Dimension",
name: "ResourceLocation"
},
{
type: "Dimension",
name: "ResourceGroup"
} ]
}
}
axios.get(url, options, params).then(response => {
console.log('response.data------', response.data);
}).catch(error => {
console.log(error);
});
}
//calling API here
await getUsage(
"subscriptionId",
"access-token"
);
Please change the format of your params from
params ={ type: "Usage", timeframe: "MonthToDate", dataset: { granularity: "None", aggregation: { totalCost: { name: "PreTaxCost", function: "Sum" } }, grouping: [ { type: "Dimension", name: "MeterCategory" }, { type: "Dimension", name: "ResourceLocation" }, { type: "Dimension", name: "ResourceGroup" } ] } }
to
params ={params:{ type: "Usage", timeframe: "MonthToDate", dataset: { granularity: "None", aggregation: { totalCost: { name: "PreTaxCost", function: "Sum" } }, grouping: [ { type: "Dimension", name: "MeterCategory" }, { type: "Dimension", name: "ResourceLocation" }, { type: "Dimension", name: "ResourceGroup" } ] } }}
Just add a "{params:" at the beginning and add a "}" at the end.
I think "params" should be a parameter of it. Please have a try.

How can I upsert multiple objects with MongoDB & Node.js?

Let's say I have an array of Movie genres like so:
[
{ id: 28, name: 'Action' },
{ id: 12, name: 'Adventure' },
{ id: 16, name: 'Animation' },
{ id: 35, name: 'Comedy' },
{ id: 80, name: 'Crime' },
{ id: 99, name: 'Documentary' },
{ id: 18, name: 'Drama' },
{ id: 10751, name: 'Family' },
{ id: 14, name: 'Fantasy' },
{ id: 10769, name: 'Foreign' },
{ id: 36, name: 'History' },
{ id: 27, name: 'Horror' },
{ id: 10402, name: 'Music' },
{ id: 9648, name: 'Mystery' },
{ id: 10749, name: 'Romance' },
{ id: 878, name: 'Science Fiction' },
{ id: 10770, name: 'TV Movie' },
{ id: 53, name: 'Thriller' },
{ id: 10752, name: 'War' },
{ id: 37, name: 'Western' }
]
and I have a connection to a MongoDB (v3.2) instance: db, and I'm using the standard mongodb Node.js driver (const mongodb = require('mongodb').MongoClient).
What I want to be able to do is one bulk upsert operation onto a collection, say genres, where the _id field maps to the id field of our genre objects.
Now, I know I could loop through each item in the array, and do a simple upsert:
for (let i = 0; i < genres.length; i++) {
await db.collection('genres').update(
{ _id: genres[i].id },
genres[i],
{ upsert: true }
);
}
But this feels wasteful and wrong.
Is there an easier way to do what should be a relatively simple task?
Thanks
Use the bulkWrite API to carry out the updates:
var bulkUpdateOps = genres.map(function(doc) {
return {
"updateOne": {
"filter": { "_id": doc.id },
"update": { "$set": { "name": doc.name } },
"upsert": true
}
};
});
db.collection('genres').bulkWrite(bulkUpdateOps, function(err, r) {
// do something with result
})
If you're dealing with larger arrays i.e. > 1000 then consider sending the writes to the server in batches of 500 which gives you a better performance as you are not sending every request to the server, just once in every 500 requests:
var bulkUpdateOps = [],
counter = 0;
genres.forEach(function(doc) {
bulkUpdateOps.push({
"updateOne": {
"filter": { "_id": doc.id },
"update": { "$set": { "name": doc.name } },
"upsert": true
}
});
counter++;
if (counter % 500 == 0) {
db.collection('genres').bulkWrite(bulkUpdateOps, function(err, r) {
// do something with result
});
bulkUpdateOps = [];
}
})
if (counter % 500 != 0) {
db.collection('genres').bulkWrite(bulkUpdateOps, function(err, r) {
// do something with the result
});
}
I would try:
db.collection('genres').update(genres, {upsert: true, multi: true});
Note: untested code...
UPDATE: to remap id field to _id:
var _genres = genres.map(function(genre) {
return { _id: genre.id, name: genre.name };
});
db.collection('genres').update(_genres, {upsert: true, multi: true});

Resources