How to get N index of array from JSON arrays - javascript

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'));

Related

lowdb - how to query multiple records?

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

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.

Vue js searching array

I am trying to search an array for query string on a json object. The returned fields are an array of filtered results. Currently, the list is returning the name field but not the number field.
computed: {
search: function () {
let self = this
let filtered = []
filtered = self.jcontacts.filter(function(contact){
return contact.firstname.toLowerCase().indexOf(self.query.toLowerCase())>=0 ||
contact.lastname.toLowerCase().indexOf(self.query.toLowerCase())>=0;
contact.email.toLowerCase().indexOf(self.query.toLowerCase()) >=0 ||
contact.phonenumber.toLowerCase().indexOf(self.query.toLowerCase()) >=0;
}
);
return this.contacts = filtered
}
},
}
The filtered method in the search method is not showing the number. An example of the json is below:
[
{
"id": 1,
"phoneNumber": [
"3908902"
],
"email": [
"jamie#fox.com"
],
"firstname": "Jamie",
"lastname": "Fox"
}]
Beware of case phoneNumber != phonenumber
phoneNumber is stored as array not string, so you cant look for it like that (use .includes() function for example)
For code formatting consider to store self.query.toLowerCase() as variable or another computed property
It is a typo. Check out field phoneNumber is filtered as phonenumber.
It is an array so you can do it as,
contact.phoneNumber.forEach( number => {
if(number.toLowerCase().indexOf(self.query.toLowerCase()) >=0)
return true;
});
I think similarly you can write it down for email as well because it is also an array.

How to make mongo validate documents before insert or update in Vertx?

I'm newbie using Vertx, I'm building a basic Api Rest with Vertx + Mongo using Javascript.
I'm looking for some way to automaticly validate the incoming documents before insert or update (for example, something like schemas in Mongoose).
I got the following:
POST entry point Inserting a new cat
var BodyHandler = require("vertx-web-js/body_handler");
var Router = require("vertx-web-js/router");
var router = Router.router(vertx);
router.post("/cat")
.produces("application/json")
.handler(BodyHandler.create().handle)
.handler(controller.createCat);
Controller's function Inserting a new cat
createCat: function (ctx) {
var response = ctx.response();
var body = ctx.getBodyAsJson() || {};
console.log('inserting cat')
connection.mongoClient.insert("cats", { name: body.name }, function (res, res_err) {
if (res_err == null) {
var id = res;
console.log("Inserted cat with id " + id);
response.putHeader("content-type", "application/json");
response.end(JSON.stringify(id));
} else {
console.log('err')
res_err.printStackTrace();
}
});
}
The problem is that I can insert empty documents resulting documents with only one field: the mongo ID.
TL;DR - I want to know if there is some way to tell Mongo that name field is ALWAYS required.
Solution I used:
mongoClient.runCommand("collMod", { collMod: "cats", validator: { $and: [ {"name": {$type: "string", $exists: true}} ] }, validationLevel: "strict", validationAction: "error" }, function(res, res_err) {
if (res_err) res_err.printStackTrace()
else console.log('The schema of cats collection has been updated')
});
In mongodb there is a concept of validation with query filters for collection: https://docs.mongodb.com/manual/core/schema-validation/#query-expressions
If the "name" field is always required, you can create your collection like this:
db.createCollection("cats", {
validator: {
$and: [ {"name": {$type: "string", $exists: true}} ]
})
you can create your own schema in a separate json file, then create your own validation method when the context is provided by ur router.
I assume different endpoint has different validation.
you can also create a middleware using gateleen
you have plenty of options, mongoose its benefits but the whole point of using mongodb is not creating a schema. Therefore, u can assume that the request should have specific mandatory fields to validate.

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