In redis how to get the value of the particular key? - node.js

In my node application i'm using redis DB to store the data.While getting the stored value using key i'm not getting the expected output.
var redis=require('redis');
var client = redis.createClient();
var pageContent={a: "a", b: "b", c: "c"};
//client.set('A',pageContent);//here i'm setting the value
client.get('A',function(err,res){
if(!err){
Object.keys(res).forEach(function(k){
console.log('key is '+k + ' value is '+res[k]);
});
}
else{
console.log('error');
}
});
Above code is not giving the stored value.While looping the result i'm getting the below error
TypeError: Object.keys called on non-object
So i have tried res.toString(); but i'm not getting the stored value instaed of that i'm getting only [object object];

The issue is that you are trying to save an object with SET. In redis, SET and GET only work with strings, so the reason you get [object Object] back is that's the string which was saved in redis -- the string representation of your object.
You can either serialize your objects as e.g. JSON, using JSON.stringify when saving, and JSON.parse when reading, or you can save your objects as redis hashes, using HMSET when saving, and HGETALL (or HGET / HMGET) when reading.
Edit: Note, though, that if you decide to use redis hashes, you cannot have "nested" objects -- i.e., you cannot store an object where one of the properties is an array or another object. That is,
{
a: 1,
b: 2
}
is okay, while
{
a: {
b: 2
}
}
is not. If you have such objects, you need another model (JSON with SET/GET works perfectly well in this case).

Related

MongoDB - NodeJS - loosing ObjectId when serializing to JSON

Trying to write / export some data from MongoDB to a file, where later I'd like to read/update them back.
filehandle = await fs.promises.open(params.credentialsFilename, 'w');
// ... some other code
let records= await mongoConn.db(params.db).collection(COLLECTION_RECORDS)
.find({}).toArray();
for(const anObj of records) {
console.log('[exportMongoDbWriteToFile] writing _id: ', anObj._id);
console.log(anObj);
await filehandle.write(JSON.stringify(anObj, null, 2)); // start array
// await filehandle.write(anObj); // doesn't work with an object
}
Th problem is that JSON.stringify(anObj) converts the ObjectId(hex_id) to a string of hex_id for the _id property (for any property using the ObjectId reference).
This is a problem as reading the data back to the MongoDB the string hex_id is not/ is different than ObjectId(hex_id) (as far I know).
However console.log(anObj); actually writes the full JSON with the ObjectId notation, not sure how the object is serialized for the console, we'd like to have the same output written into the file too.
Edit: we're using the default mongodb library

Node.js Firestore forEach collection query cannot populate associative array

In this simplified example, associative array A cannot be populated in a Node.js Firestore query---it's as if there is a scoping issue:
var A = {};
A["name"] = "nissa";
firestore.collection("magic: the gathering")
.get()
.then(function(query) {
query.forEach(function(document) {
A[document.id] = document.id;
console.log(A);
});
})
.catch(function(error) {
});
console.log(A);
Console output:
{ name: 'nissa' } < last console.log()
{ name: 'nissa', formats: 'formats' } < first console.log() (in forEach loop)
{ name: 'nissa', formats: 'formats', releases: 'releases' } < second console.log() (in forEach loop)
Grateful for any assistance, please request for further detail if needed.
Data is loaded from Firestore asynchronously, and while that is happening, your main code continues to run.
It's easiest to see what that means by placing a few logging statements:
console.log("Starting to load data");
firestore.collection("magic: the gathering")
.get()
.then(function(query) {
console.log("Got data");
});
console.log("After starting to load data");
When you run this code, it prints:
Starting to load data
After starting to load data
Got data
This is probably not the order that you expected the logging to be in. But it is actually working as intended, and explains the output you see. By the time your last console.log(A); runs, the data hasn't been loaded yet, so A is empty.
The solution is simple, but typically takes some time to get used to: all code that needs the data from the database must be inside the callback, or be called from there.
So something like this:
var A = {};
A["name"] = "nissa";
firestore.collection("magic: the gathering")
.get()
.then(function(query) {
query.forEach(function(document) {
A[document.id] = document.id;
});
console.log(A);
})
Also see:
Array of JSON object is not empty but cannot iterate with foreach, show zero length
NodeJS, Firestore get field
Unable to add Google markers inside a loop, a more complex problem, calling multiple asynchronous API
scope issue in javascript between two Functions, which also shows using the more modern async and await keywords, instead of then()
How to get data from firestore DB in outside of onSnapshot, which uses an onSnapshot listener instead of get()

NodeJS Express: how to get object item

I try to create a simple login form and fail to validate the password from the MongoDB.
First I create the .post route for the form validation and then I get the MongoDB data which I want to compare with the form.
Here is my code:
app.post('/users', (req, res) => {
const reqUser = req.body.params.name
const reqPW = req.body.params.password
// connect to mongoDB
const collection = client.db().collection("users")
collection.find({name: reqUser}).toArray(function (err, results) {
if (err) {
console.log(err)
res.send([])
return
}
else {
console.log('RESULT', results) // returns the object
console.log('RES PW', results.password) // returns undefined
// this does not work
Object.keys(results).forEach(function(key) {
console.log('key is: ', key); // returns 0
});
// validate user+pw
if (!reqUser || !reqPW/*|| reqPW !== password*/) {
return res.status(401).end()
}
// send result to frontend
res.send(results)
res.end
}
})
})
So, I get my object returned in results but I cannot get the data from the object.
I also tried to convert it to an array with Array.from() but that didn't work either.
Please note that I did not yet implement hashing and salting the passwords yet, as I thought I want a working validation first. Do I need to implement those first?
I just checked the doc:
The toArray() method returns an array that contains all the documents from a cursor. The method iterates completely the cursor, loading all the documents into RAM and exhausting the cursor.
So toArray() will return a array, not object, therefore your results will be an array containing all the items(object) you get from the db. If you console.log(results), it should print an array rather than object.
Assuming there won't be two users have the same name, the results you get will be just an array containing one object, so you can just do:
results[0].password // get the first object's password field
Not sure if this slove your question, but based on your code thats the problem i found in it.

When implementing redis with node, how do you add multiple json object to Hmset or hset or any data type?

As for example->
var redis = require('redis');
var port=6379;
var host="127.0.0.1";
var redisClient=null;
redisClient = redis.createClient(port, host);
redisClient.on('connect',function(err,reply){
if(err)
{
console.log("Erro with connectivity");
}
else
{
console.log("connected with redis");
}
});
data variable is a multiple json object
redisClient.hset('users',data);
redisClient.hgetall('users',function(err,object){
if(err)
{
console.log("Getting Hmset Error");
}
else
{
console.log("----Retrieving HMSET--");
console.log(object);
console.log("---End Retriving HMSET");
}
});
but json is not added perfect manner .
give result like this.
data= { javascript: 'AngularJS',
css: 'Bootstrap',
users: '[object Object]',
node: 'Express',
'[object Object]': '[object Object]' }
Serialize your data befor hset. E.g.
redisClient.hset ('users', JSON.stringify (data));
Redis works with strings, you need to convert your JSON (which is actually a JavaScript object) to a JSON string:
redisClient.hset('users', JSON.stringify(data));
You will then have to parse that JSON string back into a JavaScript object when you fetch it:
redisClient.hget('users', function (err, str) {
if (err) return console.error(err);
var data = JSON.parse(str); // note this might throw an exception
});
One thing to note is that you're not passing a callback into your hset method which means it's not guaranteed to have completed by the time you call hget. You should look at fixing that too.
Redis working with this datatypes in order to manipulate JSON you have to convert in strings
redisClient.hset('users', JSON.stringify(data));
strings — a sequence of binary safe bytes up to 512 MB.
hashes — a collection of key value pairs.
lists — an in-insertion-order collection of strings.
sets — a collection of unique strings with no ordering.
sorted sets — a collection

How to create a function to access JSON index in node.js?

I am working with node-red and I would like to create my custom function to access some index from the incoming message. The incoming message looks like this
{ "node": "02010101", "base64": "Cro=" }
It comes out from the json function block in node-red (A function that parses the msg.payload to convert a JSON string to/from a javascript object. Places the result back into the payload), I can use the debug block to obtain the index base64, however if I try to do the same with my own function to proces that later, I cannot and I get the error
TypeError: Cannot assign to read only property '_msgid' of Cro=
My function is really silly for now it is just
return msg["base64"];
I understand that it complains that there is no property in the incoming message, so I would like to access to hat index, how can I do it?
EDIT: if I set the debug block to show the whole message object not just the msg.base64 itself, I get this
{ "node": "02010101", "base64": "Cro=", "_msgid": "6babd6e.f945428" }
A function node should return a whole msg object not just a string.
If you want to just send on the string value you should do something like this:
msg.payload = msg.payload["base64"];
return msg
THe solution was easy, just return the whole message and not just a field. Using the following snippet made it work.
Getting decrypted module
msg.payload = msg.decrypted;
return msg;
base64Decode
msg.payload = msg.base64;
return msg;

Resources