How to find text in json array - node.js

Im making a game and one of its functions is to join/create private rooms. Private rooms are generated randomly, but before generating a room, I want to try to be sure that the room id don't exists.
var rooms = {
'ROOM ID GENERATED RANDOMLY':
Room {
id: 'ROOM ID GENERATED RANDOMLY',
players: [],
gameState: 'WAITING',
currentCard: 'g:2',
currentPlayerIndex: NaN,
currentDirection: 1,
cardsStack: [] },
'ROOM ID GENERATED RANDOMLY':
Room {
id: 'ROOM ID GENERATED RANDOMLY',
players: [ [Player] ],
gameState: 'WAITING',
currentCard: 'g:2',
currentPlayerIndex: 0,
currentDirection: 1,
cardsStack: [] },
...
}
Already tried
var SEARCH = 'x';
for (var i=0; i < rooms.length; i++) {
console.log(rooms[i])
if (rooms[i].Room.id === SEARCH) {
return rooms[i];
}
}

Try this function
function roomIdIsUnique (newKey) {
var roomKeys = Object.keys(rooms);
for (const key of roomKeys) {
if (key === newKey) return false;
}
return true;
}
var rooms = { /* Room objects */ }
var newRoomKey = /* Generate new room key code */
if (roomIdIsUnique(newRoomKey)) {
/* Continue */
} else {
/* Do something else */
}

This question is pretty vague, but I'll do my best to answer it.
You can use Object.keys() to get an array containing the keys, and then run the Array#indexOf function on that array. It will return -1 if the key is not in the array, else it will return the index
var rooms = { "key1": { property: "123" }, "key2": { property: "abc" } }
if(Object.keys(rooms).indexOf(SEARCH) != -1) {
alert("Room id exists");
} else {
alert("Room does not exist");
}

Related

How to validate the key and value not to be empty in array?

Parameter validation
I want to ensure that the array must not be empty in any cost so that i want to validate the array
imgList= [
{
"fileType": "png",
"fileContent": "base64"
},
{
"fileType": "png",
"fileContent": "base64"
}
]
I want to validate both key and value is present or not (it should not be empty)
eg: filetype is missing
{
"fileContent": "base64"
},
eg2: value is missing
{
"fileType": "",
"fileContent": "base64"
},
Code which i have tired is
body.imgList.forEach((item) => {
var key,
count = 0;
for (let [key, value] of Object.entries(item)) {
if (item.hasOwnProperty(key) && !!value) {
count++;
}
}
var objectLenght = count;
if (objectLenght != 2) {
return cb({"status_code":400,"status":"Pass all the required fields"});
}
});
When I try this worked is died and image are uploaded with out type in s3
I hope this works, you can use isOkay function to verify if the array is valid
const isOkay = (arr)=> {
let okay = true;
for(let entry of arr){
if(!entry.hasOwnProperty('fileType') || !entry['fileType'] || !entry.hasOwnProperty('fileContent') || !entry['fileContent']){
okay = false;
break;
}
}
return okay;
}
Javascript's truthy / falsy system takes care of this for you. If the key does not exist you will get undefined when attempting to access it, which is falsy. An empty string is also a falsy value.
function validate(data) {
if (!data || !data.length) return false;
for (const item of data) {
if (!item || !item.fileType || !item.fileContent) return false;
}
return true;
}
if (validate(body.imgList)) return cb({ status_code: 400, status: 'Pass all the required fields' });;
More info on falsy: https://developer.mozilla.org/en-US/docs/Glossary/Falsy

creating nested json file in node js

Here I want to create a nested json file. I have a variable loggedPerson1 as string which takes username of the person who have logged in and that person selects the courses. I want to create the json file in such a manner that registered courses would come under that name of that user.
var exists = fs.existsSync('RegisteredCourses.json');
if(exists) {
console.log("Loading");
var data = fs.readFileSync('RegisteredCourses.json', 'utf-8');
objRegister = JSON.parse(data);
}
else {
console.log('created new ')
var objRegister = {loggedPerson1:[]};
}
app.get('/RegisteredCourses',(req,res) =>{
res.send(loggedPerson)
})
app.post('/RegisteredCourses',(req,res) =>{
var declaredCourse =
{
key: Date.now().toString(),
CourseName : req.body.CourseName,
CourseCode: req.body.CourseCode,
StartDate:req.body.StartDate,
EndDate:req.body.EndDate,
Total_Fee: req.body.Fees,
Delivery_Mode : req.body.Delivery_Mode,
Description : req.body.Description,
CourseType: req.body.CourseType
}
if(!declaredCourse.CourseName ){
reply ={
msg:"Please enter data correctly"
}
res.send(reply)
}
else{
objRegister.loggedPerson1.push(declaredCourse)
let data = JSON.stringify(objRegister, null, 2);
fs.writeFile('RegisteredCourses.json',data,finished);
console.log('RegisteredCourses updated')
function finished(err){
reply = {
status:"Success",
}
res.send(reply)
console.log(reply)
}
}
})
It's not clear whether you're looking for the structure of the JSON here or something else. The JSON structure could be something like:
{
"students": {
"studentName": "Person 1",
"Courses": {
"one": "one",
"two": "two"
}
}
}
your code to read it out with:
var data = fs.readFileSync('RegisteredCourses.json', 'utf-8');
objRegister = JSON.parse(data);
should work fine, i've used the same in my projects.

Filtering the inputs in Node.js

Here, I am fetching a data from the user. The first line contains an integer, denoting the number of entries in the phone book.
Each of the subsequent lines describes an entry in the form of space-separated values on a single line. The first value is a friend's name, and the second value is a digit phone number.
For example:
2
sam 99912222
tom 11122222
So, while processing this input, I am taking the number of entries from the user and assigning it to variable noOfIterations. For the subsequent entries, I am assigning it to a list of objects wherein the format will be : for eg. [{ sam: '99912222' },{ tom: '11122222' }].
But the problem is I get [ 'sam 99912222', 'tom 11122222' ] instead while consoling the map variable. Why do I get this?
function processData(input) {
var noOfIterations = 0;
var map = input.split('\n').filter(function (string, index){
if(index===0){
noOfIterations = parseInt(string);
}
else{
var splitStrings = string.trim().split(' ');
var obj = {};
obj[splitStrings[0]] = splitStrings[1];
console.log(obj);
return obj;
}
});
console.log(map);
}
process.stdin.resume();
process.stdin.setEncoding("ascii");
_input = "";
process.stdin.on("data", function (input) {
_input += input;
});
process.stdin.on("end", function () {
processData(_input);
});
You need to use map instead of filter to transform the input data.
function processPhoneBook(input) {
var result = input.split('\n')
.filter(function(line, index) { return index > 0 })
.map(function(line) {
var splitLine = line.trim().split(' ');
return {[splitLine[0]]: splitLine[1]};
});
console.log(result);
}
Example:
processPhoneBook("3\nana 1\npep 2") outputs [ { ana: '1' }, { pep: '2' } ]
I've removed noOfIterations var since you weren't using it. If you need to use it for further processing, you can filter the result after the mapping phase:
function processPhoneBook(input) {
var noOfIterations = 0;
var result = input.split('\n')
.map(function(line, index) {
if (index === 0) {
noOfIterations = parseInt(line);
return null;
}
var splitLine = line.trim().split(' ');
return {[splitLine[0]]: splitLine[1]};
})
.filter(function(line) { return line != null })
console.log(result);
}

Meteor, MongoDb: Double inserting to collection on few occurences

I noticed this strange behaviour, when for few users only on production, it inserts every item multiple times to collection on asynchronous Meteor call. I tried multiple things, but nothing worked. I can't test on localhost, bc it never happens to me on localhost or in production.
I spent the whole night solving this, but didn't find any solution. I suppose it's caused by new Date(), but I have to call it somewhere. The production server is in Amsterdam and it seems like it happens only for users located further outside of Europe.
I found this to be similar issue, but can't really wrap my head on how to implement - https://github.com/meteor/meteor/issues/4263
Slug is what same songs are supposed to have the same.
This is the workflow, user clicks on song that triggers addNewSong function:
addNewSong = function (track) {
Globals.current_track = track;
checkIfSongAlreadySaved();
}
I need to check if song is already in collection, if it's -> route to it, else create the new song and route to it.
checkIfSongAlreadySaved = function() {
loadPrimaryGlobalItems();
Meteor.call('checkIfSongAlreadySaved', Globals.current_song_item_slug, function(error, result) {
if( result.item ) {
Globals.current_song_item_id = result.item._id;
Globals.current_song_item_slug = result.item.slug;
routeToSongPage();
if (! (result.item.download && result.item.mp3) ) {
downloadSong();
}
}
else {
loadSecondaryGlobalItems();
var item = {
slug:Globals.current_song_item_slug,
duration:Globals.current_duration,
thumbnail:Globals.current_song_thumbnail,
title:Globals.current_cleaned_song,
album:Globals.current_track.album,
artist:Globals.current_track.artists[0],
track:Globals.current_track.name,
date:result.date,
}
Globals.current_song_item_id = Songs.insert(item);
routeToSongPage();
downloadSong();
recentSongItem(result.date);
}
});
}
Add recent song
recentSongItem = function (date) {
Recentsongs.insert({
slug:Globals.current_song_item_slug,
songId:Globals.current_song_item_id,
title:Globals.current_cleaned_song,
duration:Globals.current_duration,
date:date,
});
}
If creating new song,
downloadSong = function() {
Meteor.call('findSong', Globals.current_song, function(error, result) {
console.log(result);
if (result) {
Globals.current_song_mp3 = true;
updateSongItemDownload(result.itemDetails);
}
else {
alert('not found')
}
});
}
and update song, to add download and mp3 values.
updateSongItemDownload = function(link) {
Songs.update({
_id: Globals.current_song_item_id
},
{
$set: {
download: link,
mp3: Globals.current_song_mp3,
}
});
}
Server methods:
Meteor.methods({
checkIfSongAlreadySaved: function(slug) {
return {item: Songs.findOne({slug:slug}), date: new Date()};
},
findSong:function(song) {
ServerGlobals.current_song = song;
var result = searchSite();
return result;
},
});
EDIT:
This is my subscription, just in case it might be causing the problem:
Template.songPage.onCreated(function() {
Session.set('processing', true);
var self = this;
self.autorun(function() {
var id = Router.current().params.id;
self.subscribe('singleSong', id);
var item = Songs.findOne({_id: id});
if (item) {
if (item.download) {
createSong(item.download);
}
else if( item.download === false ) {
console.log('item not found');
}
Session.set('loader', false);
Session.set('processing', false);
}
});
});
Meteor.publish('singleSong', function(id) {
check(id, String);
return Songs.find({_id: id});
});
You can apply a unique index on the slug field to ensure the same slug can only exist once and the second operation to insert will fail and show up as an error in your callback which you can discard or alert user as you desire.
db.collection.createIndex( { slug: 1 }, { unique: true } )
You will need to clear or modify the slug name on the dups from the db before applying the index though

Find document looking inside an object

I have this document:
{
"_id": ObjectId("xxx"),
"props": {
"a": "a1",
"b": "b2"
}
}
My query looks like this:
db.collection.find({"$and": [ {"props.a" : "a1"}, {"props.b": "b2"} ]}
I get the elements of the query from GET values:
/api/search?a=a1&b=b1
So, I need a way to generate dinamically my query starting from the GET object...
I thought about something like this:
// Little helper to get the object key name by index
Object.prototype.key = function key(int) { var j = -1; for(var i in this) { j++; if(j==int) { return i; } else { continue; } } }
// My attempt
var query = [],
i = 0;
_.each(req.query, function(prop) {
var key = req.query.key(i);
query.push({"props." + key: prop});
i = i + 1;
});
But it does not work...
if I do:
_.each(req.query, function(prop) {
var key = {};
key.properties = {};
key.properties[req.query.key(i)] = prop ;
props.push(key);
i = i + 1;
});
I get this:
[{ props: { a: 'a1' } }, { props: { b: 'b1' } } ]
but in this way I could get only this query:
db.collection.find({"$and": [ { props: { a: 'a1' } }, { props: { b: 'b1' } } ]}
which is completely different from the one I've written above (this one search for a props which is exactly like the ones I've provided, instead the original looks for one which contains one of the values)
how can I do?
Ok I've found a solution, searching on google did not returned any solutions...
var query = {"$and": []},
props = [],
i = 0;
_.each(req.query, function(prop) {
var key = {};
key["properties." + req.query.key(i)] = prop ;
props.push(key);
i = i + 1;
});
query.$and = props;
In this way the query generated is exactly like I need it.

Resources