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"]
Related
I have a Collection called Notes which has a document that is an UID of the user that consists of collection of an Array of objects which look something like this
obj {[
{title:"Note 1",desc:"description 1"},
{title:"Note 2",desc:"description 2"},
{title:"Note 3",desc:"description 3"},
]}
this is the actual Firestore collection where is now allowing me to store objects with the same key using the code I wrote but If I'm trying to add it manually then I
I'm using React with Firebase and using Firestore as a database
the problem I'm facing is that if I add more objects to the array mentioned above with the same key it's not creating a duplicate Firestore is not letting me add more objects with the same key. Other than that it is running just fine.
Below is the code for adding a new Notes Collection
// this function create a new Notes Collection
const createNotes = async (title, description) => {
const uid = auth.currentUser.uid; // For document name
const notesRef = doc(db, "Notes", uid);
const data = {
note: [{ title: title, description: description }],
};
try {
await setDoc(notesRef, data);
} catch (error) {
console.log(error);
}
};
Below is the code for updating the array of objects, this was the only way I could find to add multiple objects into an array on firestore
const updateNotes = async (title, description) => {
const uid = auth.currentUser.uid;
const notesRef = doc(db, "Notes", uid);
const data = {
note: arrayUnion({ title: title, description: description }),
};
try {
await updateDoc(notesRef, data, { merge: true });
} catch (error) {
console.log(error);
}
};
Is there a solution to this?
According to your last comment:
If suppose I have added an array field such as {title:”a”,desc:”b”} in the array and if again try to add the same object it will not create a duplicate of the same object how will I be able to have multiple same objects in an array?
Please note that you cannot add duplicate elements in an array using arrayUnion. According to the official documentation:
arrayUnion() adds elements to an array but only elements not already present.
So if you need to have duplicate elements, then the single option that you is to read the document, add the duplicate element in the array, and then write the document back to Firestore.
I have a nested array of objects having path as one of the keys. The structure of the nested array is as under:
const data = [
{
Name: "item1",
path: "path1",
children:[
{
Name: "item1.1",
path: "path1.1"
},
{
Name: "item1.2",
path: "path1.2",
children:[
{
Name: "item1.2.1",
path: "path1.2.1",
children:[
{
Name: "item1.2.1.1",
path: "path1.2.1.1"
}
]
},
]
}
]
}
]
I need to concentate the path values without changing the structure of array. The expected result would be:
const newdata: [
{
Name: "item1",
path: "path1",
children:[
{
Name: "item1.1",
path: "path1/path1.1"
},
{
Name: "item1.2",
path: "path1/path1.2",
children:[
{
Name: "item1.2.1",
path: "path1/path1.2/path1.2.1",
children:[
{
Name: "item1.2.1.1",
path: "path1/path1.2/path1.2.1/path1.2.1.1",
}
]
}
]
}
]
}
]
How to do it in JavaScript?
This would be best done with a recursive Function, that iterates through your entire data structure and sets the Path by building it up while traversing your data structure.
The first version creates the path information from scratch, by using the index of each child in the array and building up the index that gets appended to the path string.
Further below i've provided changes to this version, that uses the already existing path information and concatenates the path string as you asked for.
// Recursive Function to iterate through a possible endless nested data structure
// We provide the parameter for the previous index and parentPath to build up the path string
function recursivePath(data, index = "", parentPath = "") {
// We will get an Array with all Items as 'data' which we will loop with forEach
data.forEach((item, i) => {
// We recreate the the index of the item by adding current index of
// this item in the data array to the index structure of the parent items
let itemIndex = index !== "" ? `${index}.${i+1}` : `${i+1}`;
// We do the same for the path, we take the path of the parent
// and add the path information of this item to it.
let itemPath = `${parentPath}path${itemIndex}`;
// We set the path property of this item, which will be returned
// after all items of this data are done.
item.path = itemPath;
// We check if this item has some nested childrens and if it does,
// we will repeat this process for all those childrens
if (item.children && typeof item.children.length) {
// We provide the newly created index on which those childs will build upon
// as the same with the path.
// This can be a bit confusing, but we assume here, that the function will return
//the finished childrens and we save the result to our childrens property.
item.children = recursivePath(item.children, itemIndex, itemPath + "/");
}
});
// Lastly we iterated through all Items and are sure to set the Path for all Items
// and their childrens nested inside and return the entire data array.
return data;
}
// Your Data
const data = [{
Name: "item1",
path: "path1",
children: [{
Name: "item1.1",
path: "path1.1"
},
{
Name: "item1.2",
path: "path1.2",
children: [{
Name: "item1.2.1",
path: "path1.2.1",
children: [{
Name: "item1.2.1.1",
path: "path1.2.1.1"
}]
}, ]
}
]
}];
// We use the recursive function and output the results to the console
console.log(recursivePath(data));
If you would use the stored Path value of each item, you could just append the Value onto the parentPath String and save this new String into item.path
You would just change the line in the function, that creates the itemPath a little bit and you can remove the line that creates the itemIndex.
The parameter itemIndex of the recursive function isn't needed anymore and can be removed too.
// We wont need the index anymore, as we use the already existing
// Path value for the Index of each item
function recursivePath(data, parentPath = "") {
// We create a temporary new Data variable, to hold our changed elements.
let newData = [];
data.forEach((item, i) => {
// We'll create a copy of an Object to modify
let copyItem = {};
// Object.assign() copies all enumerable properties of one object to another
// We'll then use the new object to modify all properties,
// thous the original item will be untouched.
Object.assign(copyItem, item)
// We append the path information of this items path value
// onto the parentPath string
let itemPath = `${parentPath}${item.path}`;
// Same as before
copyItem.path = itemPath;
// Same as before
if (copyItem.children && typeof copyItem.children.length) {
// We removed the itemIndex, as it isnt needed anymore
copyItem.children = recursivePath([...copyItem.children], itemPath + "/");
}
// After modification we add the object to the temporary array
// and return it after all items are modified.
newData.push(copyItem);
});
// Returning the newly created array
return newData;
}
// Your Data
const data = [{
Name: "item1",
path: "path1",
children: [{
Name: "item1.1",
path: "path1.1"
},
{
Name: "item1.2",
path: "path1.2",
children: [{
Name: "item1.2.1",
path: "path1.2.1",
children: [{
Name: "item1.2.1.1",
path: "path1.2.1.1"
}]
}, ]
}
]
}];
// We use the recursive function and output the results to the console
console.log(recursivePath(data));
console.log(data);
Fur further clarification of why we need to copy Arrays and/or Objects provided as a parameter:
Arrays and Objects arent provided as their full content, as those could be huge data structures and moving and copying those every time they are provided as parameter would cause a huge memory dump as every parameter would be a redundant content of their original data.
Therefore only references or in other languages called pointers are provided, which point or reference the memory location, where the content is stored.
If you provide an array or object for a function and modify them, the modification will be stored via the reference on the original array and therefore all further access to this variable will also have those modification.
Thats why we need to copy the content of those variables into new array or objects and return those as they are themself new references but to another array with the same but slightly modified content.
The redundancy doesn't matter, as those variables are only block/closure scoped with the prefix of let before, therefore they are garbage collected after the function resolved.
I'm currently getting data from a database of an array of objects. I need these objects to be reformatted to work with a UI package that we're using that requires these objects to look a specific way. The main array should look like this:
[{
trim: 123,
id: 123,
children: [{
trim: 123,
id: 123,
}],
}]
I'm successfully looping through the main array data and reformatting it into a new array using .map; however, I'm having issues doing the same thing but for the children key that's found in each object of the main array. Wondering if anyone could help me figure out the proper way to do this. I'll add my current code below and will be able to clarify more if needed.
if (this.$store.state.models.models) { // this is checking for the main array coming from the database
const reformattedModels = this.$store.state.models.models.map((model) => {
const tableModel = {
trim: model.name,
id: model.id,
children: // Need to loop here to reformat array of objects that goes for the children key,
};
return tableModel;
});
return reformattedModels;
}
The array that I need to loop through for the children key is one of the keys found in the main array from the backend. It's called "trims" and looks like this:
[{
name: 123,
id: 123,
}]
Create a reference to the function and call it recursively:
if (this.$store.state.models.models) {
// store the function
const mapper = model => ({
trim: model.name,
id: model.id,
// use it for children, if there are any
children: model.children?.map(mapper)
});
// use it for the models
return this.$store.state.models.models.map(mapper);
}
I'm using optional chaining (?.) to call .map() only if model.children != undefined
I want to push an object into an array which is inside another object which is inside an array,
As in the above picture likes = vote I have changed that later on,
But I am not able to push an object inside this vote array
I am using this code to push into an array
Question.updateOne(
{ _id: questionId, comments: { $elemMatch: { _id: commentId } } },
{ $push: { "comments.$.vote": { userId } } }
)
I don't know what is wrong here, in the console it shows 200 status but it is not added to the database.
Have you tried with destructuring? i.e. if you have array of likes, you can do this:
myArray= [...myArray, {myNewObject: data}]
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.