How to iterate through a string array, creating an object per item? - javascript

I have the following model:
const mongoose = require('mongoose');
const schema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
Name: String,
Author: String,
Library: String,
}, { collection: 'Books' });
module.exports = mongoose.model('Books', schema);
I have an array containing book titles strings (bookTitles). I want to iterate through that list and for each title, create a new Book object. I plan to save that in a list so I may do an insertMany to Mongo. I plan to do this as follows:
const Books = require('../models/Books');
const booksToAdd = [];
bookTitles.forEach(bookTitle => booksToAdd.push(new Books({
Title: bookTitle
})))
console.log(booksToAdd);
await Books.insertMany(booksToAdd);
I have properly set up mongoose locally and am able access the db with other services in this project. Currently, if I print the books array I get an undefined object which has me thinking I'm not properly adding the Book object to the books array. In which case adding to the Books collection wouldn't work anyways since I'm not actually adding anything. How should I be iterating through the bookTitles so to create an array of Books objects, which would be added to the mongo collection with insertMany?

Looks to me like you are almost there, i have no clue of mongo.
const Books = require('../models/Books');
const booksToAdd = [];
bookTitles.forEach(bookTitle => booksToAdd.push(new Books({
Title: bookTitle
})))
The one thing i am not sure of is why you are using booksToAdd.push(new Books
What makes sense to me is booksToAdd.push(new Object //works for my example data
const booksToAdd = [];
let bookTitles = ["first","second","third"];
bookTitles.forEach(bookTitle => booksToAdd.push(new Object({
Title: bookTitle})))
//booksToAdd
// (3) [{…}, {…}, {…}]
0: {Title: "first"}1: {Title: "second"}2: {Title: "third"}length: 3__proto__: Array(0)

We cannot see any part of the code where you initialize the bookTitles property.
If there isn't, there isn't any iteration also. Provide us with more code.
Also try to put a console.log(bookTitles) before its forEach.

Related

Mongoose deleting object ($pull) in Array does not work

I'm trying to delete an object inside an array in my DB using the $pull in Mongoose but does not work.
This is my attempt:
const listSchema = new Schema({
name: String,
items: []
});
const List = mongoose.model("list", listSchema);
const itemDeleted = req.body.checkbox;
//I get here the ID of the object inside the array
const itemListDeleted = req.body.listDeleted;
// Here the name of the object that contains the array
List.findOneAndUpdate({name:itemListDeleted},{$pull:{items:{_id: itemDeleted}}},function (err,foundList) {
if (foundList){
res.redirect("/"+ itemListDeleted);
} else {
console.log(err);
}
})
I searched for solutions and everybody recommends using $Pull but in my case, it doesn't work. I log the const and all things appear to be right.
Do you have any suggestions?

how to sort and limit firebase realtime db v9?

devs.
I am trying to make a table that will show the top scorers.
I am new to firebase v9.
problem:
I am using realtime DB for storing the name and scores of users with doc names and names are same.
as I used orderbyValue, orderbykey and orderbyChild. snapshot.val() returns an object which contains objects ( check at the bottom ) which is unordered and don't know how to access all or loop.
for limiting, I tried limitToLast which works fine but sorting doesn't.
help me to sort and limit this.
this is how my data is stored in realtime database
this is my code to fetch and try to sort
import { getDatabase, ref, set, onValue, query, orderByChild, limitToLast, equalTo, orderByValue, orderByKey } from "https://www.gstatic.com/firebasejs/9.4.1/firebase-database.js";
var namelist = $('.person');
var list = $('.scores');
// const scoreBoardRef = ref(db, 'users');
const scoreBoardRef = query(ref(db, 'users'), orderByChild('score'));
onValue(scoreBoardRef, (snapshot) => {
const data = snapshot.val();
console.log(data); // this returns object containing object and **i don't know how to deal with this.**
//console.log(scoreBoardRef);
list[0].textContent = data.score; // here i want score
namelist[0].textContent = "";//here i want name
//my main goal is to loop through top 3 or 10 data and print it to table
});
In the console, this is what I get
⬇{abcd: {…}, man2: {…}, nacho: {…}, two: {…}}
▶abcd: {name: 'abcd', score: 15}
▶man2: {name: 'man2', score: 20}
▶nacho: {name: 'nacho', score: 21}
▶two: {name: 'two', score: 18}
▶[[Prototype]]: Object
As Dharmaraj commented: the results in the snapshot are actually ordered, but when you call snapshot.val() it gets converted to a JSON object and the keys in a JSON object are by definition not ordered.
To get the results in order, loop over them with snapshot.forEach:
onValue(scoreBoardRef, (snapshot) => {
snapshot.forEach((child) => {
const data = child.val();
console.log(data);
});

How to write a mongoDB query to match any element in an array of subdocuments against any element in a Typescipt Array?

I have a mongoDB database containing Events. Each event is defined by a number of fields, including an array of genres (which are subdocuments consisting of a {genre and subGenre}).
For example: an event could be of {genre: "music", subGenre: "jazz"}, and {genre: "music", subGenre: "blues"}. See event.js - the model. In this case, 2 "genre" sub documents are added to the "genres" array in the Event document in the database.
Back in my node application - see query.ts - I am trying to work out how to run a query that lets the user search for all events that match their genre preferences.
So:
the Event is defined by an array of genres (in the database), and
the user's preferences are defined by an array of genres (in the
application).
I am looking to define a mongoDB query that returns all Events where there is a match of any 1 {genre, subGenre} combination between the 2 arrays.
I looked into $in Query Selector in the mongoDB documentation and suspect it might need to be used... but programmatically, how do I write a query that expands to include all the values in the variable "searchGenres" in query.ts?
Thanks a lot in advance for your thoughts.
event.js: mongoDB Model for 'Events" defined using Mongoose - snippet:
let mongoose = require('mongoose');
let EventSchema = new mongoose.Schema({
genres: [
{
genre: String,
subGenre: String
}
]
)};
module.exports = mongoose.model('Event', EventSchema);
query.ts:
import mongoose = require('mongoose');
let Event = require ('../models/event');
class Genre {
genre: string;
subGenre: string;
constructor (gen: string, sub: string) {
this.genre = gen;
this.subGenre = sub;
}
}
async function runQuery()
{
let searchGenres : Array<Genre> = new Array<Genre>();
// populate searchGenres with some data here... e.g.
const searchGenre1 : Genre = new Genre ('music', 'jazz');
const searchGenre2 : Genre = new Genre ('music', 'rock');
searchGenres.push(searchGenre1);
searchGenres.push(searchGenre2);
// Query logic here:
// Return all events from the database, if the 'genres' array
// in the document matches any element in the searchGenres array
// defined above..
const events = await Event.find ({
'genres': {?help? }
});
}
```
After some self-education today, I have come up with a solution, which I am happy with - to append to end of query.ts:
type GenreQuerySelector = { genres: { $elemMatch: { 'genre': string; 'subGenre': string; }; }; };
let querySelectors : Array< GenreQuerySelector > = new Array< GenreQuerySelector >();
for (let genre of searchGenres) {
const genreQuery : GenreQuerySelector = {
genres: {
$elemMatch: {
'genre': genre.genre,
'subGenre': genre.subGenre
}
}
};
querySelectors.push(genreQuery);
};
const events = await Event.find ({ $or: querySelectors }).exec();

Return undefined when query to model

I want to access the content of array of document in my model, but I can't and return undefined.
here is my model(Project.js):
var mongoose = require('moongoose');
var Schema = mongoose.Schema;
var User = require("./Users");
var ProjectSchema = new Schema({
name: String,
description: String,
owner: {
type: mongoose.SchemaTypes.ObjectId,
ref: "User"
},
contributor: [{
type: mongoose.SchemaTypes.ObjectId,
ref: "User"
}]
});
module.exports = mongoose.model('Project', ProjectSchema);
and my Api:
var Project = require('./Project')
await Project.find({owner: userId, name: name})
.then(project => {
console.log(project);
console.log(project.contributor);
}).catch(err => {
res.status(500).send({
message: err.message
});
});
when i try console.log(project); return expected output but in console.log(project.contributor); return undefined
I've also searched the web but couldn't find anything right and clear solution
I appreciate any help :)
As you are expecting to find only one project, change find by findOne method. Other case you are searching for several projects and you are going to receive an array instead of an object.
Your output from Project.find() (See) will be an array of objects from the database.
If you will only have 1 object as a result then you can use project[0].contributor because project is an array with 1 object inside it, which is on the index 0.
If the result might have many objects in the array then you should iterate through the result to get each of the data individually.
project.forEach(p => console.log(p.contributor))

How do I push to an embedded array?

I'd like stores (grocery stores, restaurants, gyms, etc) with different types of sections. They're unique to the object in the array. A gym is going to have different sections than a grocery store, for example.
var UserSchema = new Schema({
store: [
{
name: String,
section: Array,
}
],
});
I got this working with simply store: Array (in the UserSchema), but I changed store to an object inside the array. How do I push to objects within store?
$scope.storeUpdate = function(){
Users.get({email:$scope.global.user.email}, function(user3) {
// Changing store.push to store.name.push gives the error: user3 not defined
// If in UserSchema the store: type: Array, then user3[0].store.push works fine
user3[0].store.section.push($scope.datStore.name);
user3[0].$update(function(response) {
// This just updates user changes on the webpage
Users.query({}, function(users) {
$scope.users = users;
$scope.global.user = response;
});
});
});
};
Edit: Should I just embed a second schema?
user3[0].store.name.push($scope.datStore.name);
you're pushing into store.name which is a string object (not an array)
you can change your schema if you want to push into store.name
var UserSchema = new Schema({
store: [
{
name: Array,
section: Array,
}
],
});
Then you'll be able to push into user3[0].store.name
EDIT
you have Schema as there's an object having property store, where store is an array containing objects, and those objects will have properties name and section.. So just push objects into store.
Just decide what the schema should be, your aim is to push data into store right?
so you have to build up the object before pushing. for example
var obj ={
name: $scope.datStore.name,
section: ["grocery","utensils"]
}
then just push your object into the store array.
user3[0].store.push(obj);
In short, create the object to be pushed into store before pushing it into store array
you can push data to the section like this (before pushing the object into store
var obj ={
name: $scope.datStore.name,
section: []
}
obj.section.push(someSource1.section); //grocery
obj.section.push(someSource2.section); //utensils
then push into store
user3[0].store.push(obj); // here object being pushed will be {name:"",section:["grocery","utensils"]

Categories