Cloud Functions problem, query resulting in an Array? - javascript

I need to get inside of itens to go into some item, than into product to get the "ean" field and
check if some product have the "ean" from the body request.
My database is organized like that:
"cart": {
"itens": {
"0": {info here},
"1": {info here}
"2": {
"more info here",
"product": {
"avaliable": true"
"quantity": 231,
"ean": "0000001312"
}
continue listing until 47
But when I execute my cloud function:
exports.getItemByEan = functions.https.onRequest(async (request, response) => {
const db = admin.database();
const itens = db.ref();
const eanRef = itens.child('carrinho').child('itens');
const query = eanRef.orderByKey();
try {
const dataSnapshot = await eanRef.once('value');
response.send(dataSnapshot.val());
} catch (error) {
console.log(error)
}
})
});
But i need to get inside of an iten, and then inside "product" field and than get the "ean", but the result of this is like an Array insted of an object, and without the keys appearing:
[
{,
"product": {
"avaliable": true,
"quantity": 9183
"ean": "0000000000017",
},
{
"product": {
"avaliable": true,
"quantity": 131
"ean": "0000000044790",
},
},
.....continues
I want to things, understand why the result of the query is an Array and not an Object with the Keys before the itens like in the Firebase Database, and then how is the better way to find the specific product by Ean.
I can't even do like
const db = admin.database();
const itens = db.ref();
const eanRef = itens.child('cart').child('itens').child('product'); // This doesnt works, just returns nothing, why ?????
// Isn't "product" field inside the item ?

If your database keys are all numbers, then instead of an object, you will get an array with the same items, where the indexes of the array are the same as the keys of the nodes in the database. Your code needs to be prepared for this. So, if you want the client to receive an object instead of an array, you will have to convert it yourself.

Related

Find matching items in array of object values from array of filter criteria

I have some data (json) that looks like this:
[
{
"name": "Enterprise Networking",
"technology": "Networking"
},
{
"name": "Enterprise Networking",
"technology": "Networking"
},
{
"name": "Wireless Insights",
"technology": "Mobility and Wireless"
},
{
"name": "Mobility Insights",
"technology": "Mobility and Wireless"
},
{
"name": "Lock it down",
"technology": "Security"
},
{
"name": "Collaboration",
"technology": "Security"
}
]
I am trying to find matches based on an array of filtering options for one field named 'technology' in this example. For example, my filtering criteria will be ["Networking", "Security"]. I would expect to return all objects that have 'Networking' and 'Security' as their technology, excluding 'Mobility and Wireless' in this example.
I have figured out how to do it with just one filter criteria using:
result = learningMapsDataObj.filter(el => el.Technology === filter3[0].value);
I've tried adding a method that will loop through the the filter array, but can't get it to work.
result = learningMapsDataObj.filter(el => el.Technology === myloopingArrCheckFunction(el.technology, filters3));
I know I'm close, but haven't had to dev in a while and my multidimensional brain isn't working.
Approaches
You can check if el.technology is included in your array of values to filter by:
const allowedTechnologies = ["Networking", "Security"];
learningMapsDataObj.filter(el => allowedTechnologies.includes(el.technology))
Alternatively, you can also check if el.technology is like some of the values to filter by:
const allowedTechnologies = ["Networking", "Security"];
learningMapsDataObj.filter(el => { // Linebreak (thus function body) for readability
return allowedTechnologies.some(allowedTech => allowedTech === el.technology);
})
Map to string array
It seems your filter is in a form similar to this:
const filter = [
{ value: "Networking" }.
{ value: "Security" }
];
But it would be easier to use if it was in the form as shown in my examples above. You can achieve that by mapping the filter elements to their values:
const filter = [
{ value: "Networking" }.
{ value: "Security" }
];
const filterValues = filter.map(el => el.value);
// Now you can use filterValues like allowedTechnologies
let result = learningMapsDataObj.filter(el => el.technology === "Networking" || el.technology === "Security" );
You can filter the array with an array of criterias like this
const filterCriteria= ["Networking", "Security"]
const filteredArray = learningMapsDataObj.filter((item) => filterCriteria.includes(item.technology));
if you want to set a variable for fields you want to filter, you can also do something like this
const filterField = 'technology'
const filterCriteria= ["Networking", "Security"]
const filteredArray = learningMapsDataObj.filter((item) => filterCriteria.includes(item[filterField]));

How to push an item to the array inside JSON Object?

I am trying to make inventory functionality using Discord.js and struggling on how to push an item to the array inside JSON Object.
Inside the JSON, every user with unique 'userID' has their own array 'inventory'.
The thing I want to achieve is:
After user types 'get' command in the chat, the item is pushed to the inventory array and the JSON file is updated.
.json file:
{
"userID": {
"inventory": []
}
}
.js file:
const item = itemName
inventory[userID] = {
inventory: inventory[userID].inventory + item,
}
fs.writeFile('./data/inventory.json', JSON.stringify(inventory), err => {
if (err) console.log(err)
})
Output (after using command twice):
{
"userID": {
"inventory": ["itemNameitemName"]
}
}
Expected output (after using command twice):
{
"userID": {
"inventory": ["itemName", "itemName"]
}
}
The thing I want to achieve is: After user types 'get' command in the chat, the item is pushed to the inventory array and the JSON file is updated. I suppose I need to use .push() somewhere, but I tried it million times in all configurations I could think of and it always throws an error, that .push() is not a function.
Instead of making a new object for the user every time you want to update the inventory, it would be much easier if you can just push the item to the inventory instead of reassigning. #DanielAWhite wrote the correct solution but I think you misunderstood where to put that particular piece of code. What you might have tried is this:
const inventory = {
"userID": {
"inventory": ["testOne"]
}
}
const item = "test"
const userID = "userID"
inventory[userID] = {
inventory: inventory[userID].inventory.push(item),
}
console.log(inventory)
Instead, what the correct way was to do away with the inventory[userID] = {} part and just directly push the item to the inventory by doing this:
const inventory = {
"userID": {
"inventory": ["testOne"]
}
}
const item = "test"
const userID = "userID"
inventory[userID].inventory.push(item)
console.log(inventory)
(Note: I edited the code a little bit so that you could try to run this code right here, but this should work with your fs.writeFile as well
Try this :
let rawdata = fs.readFileSync('inventory.json');
let inventory = JSON.parse(rawdata);
inventory["userID"] = {
inventory: [...inventory["userID"].inventory, item],
}
fs.writeFile('./inventory.json', JSON.stringify(inventory), err => {
if (err) console.log(err)
})

Loop to get value based on key name

Below is the JSON response I am getting. From this JSON response, I want to get the value of "fees" based on "detailComponent" with "FULL_FEE" only. But, somehow it gets the last value of "detailComponent" with "SUB_FEE" or others which is not correct.
I am sure not how to make this for loop condition to fix my issue. Can help to guide pls?
let data = {
"status": "SUCCESS",
"result": {
"originData": {
"detailType": "MSG",
"origin": [
{
"details": [
{
"detailComponent": "FULL_FEE",
"fees": 13564.00
},
{
"detailComponent": "SUB_FEE",
"fees": 8207.60
}
]
}
]
}
}
}
var getData = data.result.originData.origin[0].details[0].detailComponent;
console.log('getData: ', getData);
You can convert the array into a dictionary by the key (detailComponent) and the number (fees).
// Create Array
var items = [];
// Loop Through It
data.result.originData.origin[0].details.forEach((el, index) => items[el.detailComponent] = el.fees);
// Test
console.log(items["FULL_FEE"]);

How to display a json get request where _something_ equals _anothersomething_ (Node.js, MongoDB)

I have an id inside req.params.id.
var id = req.params.id // let's say this is 2
And let's say I have this from MongoDB:
[
{
"text": "hello",
"fromId": "1"
},
{
"text": "hi",
"fromId": "1"
},
{
"text": "hey",
"fromId": "2"
},
]
I use this to query through:
const message = await Message.find().select('text fromId');
const fromId = await Message.distinct('fromId');
And I want something like this (but of course this code is incorrent):
res.json(message).where(id === fromId);
So I want to get only this because my id is 2 and fromId is 2:
{
"text": "hey",
"fromId": "2"
},
I want the get request res.json() to display only the ones where id is equal with fromId.
Pass a filter object to find function to fetch only those documents where fromId is equal to req.params.id
const message = await Message.find({ fromId: req.params.id })
I believe you're simply looking for
const message = await Message.findOne({"fromId": "2"})
You should also add .lean() so it returns simple JSON and is faster, and also .exec() to be non-blocking.
Full code :
const message = await Message.findOne({fromId: req.params.id}).lean().exec();
res.json(message);
Why are you not using Mongoose? If it's a personal preference to not use ORMs, I understand but if you do change your mind. It's as simple as
const message = await Message.findById(id); // This only takes mongoDB ids as arguments
// Use this for another general field
const message = await Message.findOne({fromId : id})
res.json(message).status(200);
You could also wrap it inside a try catch block to handle any errors if the document with the id wasn't found.

MongoDB/Mongoose Query Builder

I am trying to build a query builder which will allow me to filter the data based on the parameters entered by user. My Data Model is like so:
{
"_id": {
"$oid": "871287215784812"
},
"tags": [
"school",
"book",
"bag",
"headphone",
"appliance"
],
"consultingDays": 57,
"client": "someOne",
"subSector": "something",
"region": "UK",
"__v": 0
}
Currently my Query Builder looks like this:
app.post('/user/test',function(req, res) {
var query = {};
//QUERY NO.1 - This works perfectly
if (req.body.region){
query.region = req.body.region
console.log(query.region)
}
// QUERY NO.2 - This works perfectly
if (req.body.subSector){
query.subSector = req.body.subSector
}
Project.find(query, function(err, project){
if (err){
res.send(err);
}
console.log(project);
res.json(project);
});
});
My Question:
I want to create a query which will take input from user and parse the "tags" array and return the required JSON.
For example:
If the user requests an object which contains "school", "book", "bag" it will return the object as seen my data model above. But if the user requests an object with "school", "book", "ninja Warrior" it won't return any data as no object within the database contain all those 3 strings.
What I have tried:
I have tried the following
if (req.body.sol){
query.solutions = {"tags" : {$in: [req.body.sol]}}
}
OR
if (req.body.sol){
query.solutions = {$elemMatch:{tags: req.body.sol}}
}
OR
if (req.body.sol){
query.solutions = { tags: { $all: [req.body.sol]}}
}
The requests were sent like so and they returned an empty array:
Also the issue is that the user will get dropdown options. For example he/she might get 3 dropdown boxes. Each dropdown box will display all the five options in the tags array. The user will select a value for each dropdown box. And then filter the result. Because there might be an object within the database that contains "book", "bag", "shoes" within the tags array. The user can select any combination of those five keywords in the tags array
Does anyone know how I can fix this?
You need to send an array as sol so in Postman you should change sol with sol[0], sol[1], etc.. Then use this:
if (req.body.sol){
query.solutions = {"tags" : {$in: req.body.sol}}
}
Without the [] because req.body.sol is an array yet.
I have implemented a simple query build for nested objects:
const checkObject = (object) => {
let key;
const status = Object.entries(object).some(([objectKey, objectValue]) => {
if (typeof objectValue === "object" && objectValue !== null) {
key = objectKey;
return true;
}
return false;
});
return { status, key };
};
const queryBuilder = (input) => {
// Array verification not implemented
let output = {};
_.each(input, (value, key) => {
if (typeof value === "object" && value !== null) {
_.each(value, (nestedValue, nestedKey) => {
output[`${[key, nestedKey].join(".")}`] = nestedValue;
});
} else {
output[key] = value;
}
});
const cacheCheckObject = checkObject(output);
if (cacheCheckObject.status)
return { ..._.omit(output, cacheCheckObject.key), ...queryBuilder(output) };
return output;
};
I have not implemented array, but with some small work you can do it work. The same for Mongo operators. The complete example can be seen on Gist.

Categories

Resources