lowdb - how to query multiple records? - javascript

I'm using https://github.com/typicode/lowdb for a small project. I need a query which searches multiple records and returns each record it finds as an array.
For example, for a db such as:
"records": [
{
"id": "sadohfdsf",
"username": "user1",
"data": "abc"
},
{
"id": "tiyuykuy",
"username": "user1",
"data": "xyz"
},
{
"id": "tryehhrt",
"username": "user2",
"data": "tyu"
}
]
I'd like to query all the records for username: "user1" and get all the records for that user in an array.
I've tried the default:
const user = await db.get('records')
.find({ username: "user1" })
.value();
return user;
but it only finds the first record in the db.
What's the correct way to find multiple records in lowdb?

NOTE: I don't use LowDB
Judging by the docs, I think it's not possible to find multiple records in LowDB. Instead, you can use the Array#filter method.
// Assuming the following returns an array of your object
const users = await db.get('records')
.value();
// We can `filter` the user(s)
const result = users.filter(
user => user.username === 'user1' /* or any other username */
);

Use filter instead of find .
const users = await db('records').filter({ username: "user1" });
Ref: https://github.com/typicode/lowdb/issues/185
Left join with lowdb
Multipe filters means use chain() as well

Related

How to get N index of array from JSON arrays

Hi I have JSON file that have users nickname, password and token. I'm using a find function to find users from their nicknames. I want to get tokens too.
[
{
"user": [
"bombali",
"reYiz_2031",
"GcjSdUMp"
]
},
{
"user": [
"johndoe",
"testpasswd1_s",
"SdNFccRT"
]
}
]
This is my JSON data file.
I'm checking if nicname is taken or not using this code:
function isUsernameTaken(username) {
const user_Database = require(`${config.path_users}`);
const finded_Name = user_Database.find(
({ user }) => user[0] === username.toLowerCase()
);
if (finded_Name === undefined) {
console.log("This username is usable");
} else {
console.log("This username is unusable");
}
}
Now I want to get token from json by using username and password to use filter. I don't want to use token:SdNFccRT in array. Is it possible? Thanks for all replies.
Using .filter() isn't the best choice in this case. With .find(), the search will stop once one element has been found, but .filter() will keep on going when it doesn't have to.
Given the username and password, you can find the token with a single .find() statement that compares each user object's username and password, then returns the token of the match. You can also use optional chaining to return undefined if no match is found. Like this:
const getToken = (data, uname, pass) => data.find(({user}) => user[0] === uname && user[1] === pass)?.user[2];
const data = [{
"user": [
"bombali",
"reYiz_2031",
"GcjSdUMp"
]
},
{
"user": [
"johndoe",
"testpasswd1_s",
"SdNFccRT"
]
}
];
console.log(getToken(data, 'bombali', 'reYiz_2031'));
console.log(getToken(data, 'none', 'none'));

Firebase Realtime Database - orderByChild().equalTo() does not return expected node

I have Firebase Realtime Database data structured as below where I want to replace "-preliminaryId" with "-ultimateId123" in the "contacts" and "notes" nodes. To perform this I will delete the old nodes and replace them with new nodes.
"prel":{
"-preliminaryId": {
"email" : "hello#bye.com"
}
},
"contacts": {
"-ABC": {
"-BCD": {
"email": "bye#nowhere.com",
"uid" : "-123456WWWXYz"
},
"-preliminaryId": {
"email": "hello#bye.com",
"uid": "-preliminaryId"
}
}
},
"notes": {
"-noteIdone": {
"access": {
"members": {
"-preliminaryId": 1
}
}
},
"-noteIdtwo": {
"access": {
"members": {
"-realId1234": 1
}
}
}
}
The new id for email "hello#bye.com" should be "-ultimateId123".
(I cannot store email as keys in Firebase Realtime Database.)
I begin by fetching the preliminary id to replace.
const prelSnap = await dbRoot.child('prel').orderByChild('email').equalTo('hello#bye.com').once('value')
const prelData= prelSnap.val()
console.log('prelData', prelData)
const oldId = Object.keys(prelData)[0]
The prelData variable will be
{ -preliminaryId: { email: 'hello#bye.com' } }
However, I would prefer it to just be
{ email: 'hello#bye.com' }
so I can get oldId by prelSnap.key instead of Object.keys(prelData)[0].
However, my real hurdle is fetching contacts
const contactSnaps = await dbRoot.child('contacts').orderByChild(`${oldId}/uid`).equalTo(oldId).once('value')
console.log('contactSnaps', contactSnaps.numChildren())
contactSnaps.forEach((contact)=>{
console.log('contactData', contact.val())
const userId = Object.keys(contactData)[0]
...
// Replace the contact node
myPromises.push(dbRoot.child(`contacts/${userId}/${newId}`).set(contactObj)) // Create new contact data
myPromises.push(dbRoot.child(`contacts/${userId}/${oldId}`).remove()) // Delete old contact
...
})
This will get me ALL contacts. The logout from console.log('contactData', contact.val()) will be:
numChildren 1
contactData {
"-BCD": {
"email": "bye#nowhere.com",
"uid" : "-123456WWWXYz"
},
-preliminaryId: {
"email": "hello#bye.com",
"uid": "-preliminaryId"
}
}
Hardcoded example:
const contactSnaps = await dbRoot.child('contacts').orderByChild('-preliminaryId/uid').equalTo('-preliminaryId').once('value')
console.log('contactSnapsHC', contactSnaps.numChildren())
contactSnaps.forEach((contact)=>{
const contactData = contact.val()
console.log('contactDataHC', contactData)
})
Output from above hardcoded example:
contactSnapsHC 1
contactDataHC { -BCD: { email: "bye#nowhere.com", uid : "-123456WWWXYz" }, -preliminaryId: { email: "hello#bye.com", uid: "-preliminaryId" } }
My guess is that this might be somewhat related to my issue with the first query?
When performing the same type of query on notes, all works well though.
nodeSnaps = await dbRoot.child('notes').orderByChild(`access/members/${oldId}`).equalTo(1).once('value')
console.log('notes', nodeSnaps.numChildren())
nodeSnaps.forEach((node)=>{
console.log('notesData', node.val())
...
}
The output here will be:
notes 1
notesData { "access": { "members": { "-preliminaryId": 1 } } }
I expected the first two queries to return result at the same node level as the notes query.
How can I query the database to return the result shown below?
prelData { email: 'hello#bye.com' }
contactData { email: 'hello#bye.com', uid: '-preliminaryId' }
Kind regards /K
I think your confusion is about what the query returns here:
dbRoot.child('contacts').orderByChild('-preliminaryId/uid').equalTo('-preliminaryId')
Firebase queries operate on a flat list. Since you query contacts, the nodes returned will be child nodes of contacts. Specifically, it returns any child node of contact for which a property -preliminaryId/uid exists, which has a value of -preliminaryId. In your example that is true for the node at contacts/-ABC, which is what the query returns for me.
For example, when I add another sibling node on the same level as ABC:
"contacts": {
"-ABC": {
"-BCD": {
"email": "bye#nowhere.com",
"uid" : "-123456WWWXYz"
},
"-preliminaryId": {
"email": "hello#bye.com",
"uid": "-preliminaryId"
}
},
"DEF": {
"-HKI": {
"uid": "another id"
}
}
},
Your query in this case still only returns the -ABC node, since that's the only one where a -preliminaryId/uid exists with the correct value.
For a working example of this, see: https://jsbin.com/wivukeq/edit?js,console

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.

Cloud Functions problem, query resulting in an Array?

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.

Issues Deleting a item in a user Model (array), not sure how to save the result

I have a user with various post ID's inside of my mongodb database, I am using mongoose to talk to it.
this is the user object
[
{
"premium": true,
"max_posts": 55,
"posts_made": 52,
"posts": [
"5e10046c0be4f92228f6f532",
"5e1005a9dceb1344241c74c5",
"5e100753a6cfcb44d8f1fa09",
"5e1007bea6cfcb44d8f1fa0a",
"5e1008149324aa1d002a43be",
"5e1009562826a308a0812e92",
"5e100a625e6fcb2c90a07bec",
"5e157143536d6e04a80651bd",
"5e1e320dc749f23b189ccef7",
"5e1e3273546d55384c3a975c",
"5e1e340183d0b0080816cedd",
"5e1e368bd921f3194c22b3d2",
"5e1e3732d921f3194c22b3d3",
"5e1e3a6f9b3017189cff0fe2",
"5e1e3c1a8c38f11c60354052",
"5e1e9ab208d0a5416828d0a3"
],
"_id": "5e0fe3f33c2edb2f5824ddf2",
"email": "user#gmail.com",
"createdAt": "2020-01-04T01:01:39.840Z",
"updatedAt": "2020-01-15T04:53:08.987Z",
"__v": 16
}
]
So, I make a request to the database using express, and I try to filter the array, using an id of one post, then I ask express to save that modified user model...
router.delete('/testing', (req,res,next) =>{
userModel.findOne({ email: req.body.author }, function(error, user) {
user.posts.filter(item => item != req.body.postid)
user.save((err) => {
console.log(err);
});
res.json(user)
});
});
my request in postman :
As you can see, the item is still there in that array... checking the console.log.
Please Advise as I am having doubts, thanks.
You no need to find & update the document of user, which makes two DB calls, plus .filter(), try this :
router.delete('/testing', (req, res, next) => {
userModel.findOneAndUpdate({ email: req.body.author},
{ $pull: { "posts": req.body.postid } }, { new: true }, function (error, user) {
res.json(user);
});
});
Here we're using .findOneAndUpdate() as it returns the updated user document which you need to send back.
This is how I would do it using $pull operator.
The $pull operator removes from an existing array all instances of a value or values that match a specified condition.
userModel.update(
{email: req.body.author},
{ $pull: { posts: { $in: [ req.body.postid ] } } },
{ multi: true }
)
For now it seems like you are passing single postid in request body. In future if you needed to delete multiple posts at the same time, you can use the same query by just replacing { $in: [ req.body.postid ] } with { $in: [ ...req.body.postid ] }

Categories

Resources