How to create fields for filling in admin-bro when editing a record with dynamic key names that were not originally specified in the mongoose model schema, for further possible editing of these fields through the admin-bro interface ?
Model schema
const {Schema, model, Types} = require('mongoose');
const Session = new Schema({ data: {}, fields: {name:Schema.Types.Mixed, pit: String,} })
Row in collection
row = { data: {name:'test', pit:'test'}, fields: {name:'test', pit:'test'} }
data - this is create dynamical
fields - this is set in model schema
Example
Row Create new - example
{data: {unknown_name:'test', unknown_name1:'unknown text'}};
OR
{data: {test:'test', test1:'unknown text'}};
OR
{data: {piter:'name', pen:'surname'}};
OR
{data: {name:'piter', surname:'pen'}};
enter image description here
Need in AdminBro view set how on screen.
Data Name input Data Pit input
Im not know what set and...
Related
I have a project in nodejs with a mongodb database and i would like to create a brand new deployment of the project for another customer so i need the same database structure without old data.
What should i do?
Do i have to create all collections manually or there's a way to script just the database schema?
EDIT
I have been told that mongoose will automatically create the collection if it doesn't exist when the connection to the database is opened
I always prefer using the MVC model.
I will share on of my model file with you to understand how you can write a re-usable database schema code.
const expenseCollection = require('../db').db().collection("expenses");
const ObjectID = require('mongodb').ObjectID
const Money = require('./Money')
let Expense= function(data, userId){
this.data = data,
this.authorId = new ObjectID(userId)
this.errors =[]
}
//MAZZA BELOW ARE THE FIELDS MENTIONED THAT YOU MAY WANT TO HAVE IN YOUR SCHEMA
Expense.prototype.cleanUp = function(){
this.data ={
amount: Number(this.data.amountSpent),
item: this.data.item,
purchaseDate: new Date(this.data.purchaseDate),
notes: this.data.notes,
status: false,
expType: this.data.expType,
authorId : this.authorId,
}
}
module.exports = Expense
Also, I will share with you how can you pass the data in this constructor.
(From one of the of the controller file)
const moneyController = require('./moneyController')
const Expense = require('../models/Expense')
exports.saveExpense = async function(req, res){
let data = {
balance:0,
}
let money = new Money(data)
await money.addMoney(req.session.user_id)
await money.subtractBal(req.body.amountSpent, req.session.user._id )
//MAZZA FOCUS ON THE BELOW LINE:
let expense = new Expense(req.body, req.session.user._id)
await expense.saveExpense()
res.redirect('/')
}
Primarily, the model will be a file, wherein you can write the reusable schema script.
Consider making separate model for each collection, that is 1 collection = 1 new model in your code.
Also, in the above code that I shared with you, it will automatically create the collection even if it does not already exist in the mongodb.
Trying to design a Form Entry web app and i've rarely used MongoDB before.
Wondering if this is the best practice for storing form (document) data inside a collection.
const mongoose = require('mongoose');
// Create Schema and Model
const documentSchema = mongoose.Schema({
nps: [{ // New Promotion Submission
documentId: Number,
orgid: Number,
documentFields: [{ // Form Fields
id: Number,
dateTimeSubmitted: Date,
title: String,
productDescription: String,
productUnitSize: Number,
productCartonQty: Number
}]
}]
})
const documents = mongoose.model('documents', documentSchema);
module.exports = documents;
This is absolutely fine design, couple of things to look at:
Make sure you introduce validation on your schema fields, mirror the same validation pattern on the frontend form fields also.
Be consistent with your naming: if you use camelCase in documentId make sure to also origId
Convention says you name a model in singular form, i.e. "Document" not "documents".
If you're going to re-use the documentFields schema anywhere else in other models, make sure to store it as a separate schema and import as needed.
I have multiple tables named "register_yyyymmdd"(horizon sharding) to save logs in mysql.I define a Model like:
Register.js
const Register = sequelize.connection.define('Register',
{
ip : Sequelize.STRING,
log_time : Sequelize.INTEGER
},
{
tableName : 'register_20180516'
};
module.exports = Register;
When I trying to save data like:
Register.build(data).save();
How can I specify the table name(base on date) which I want to insert? For example, it may insert data in to table register_20180517 when today is May 17 2018.
I have data of array of objects i.e,
$arrayObj=[{name:'Jack'},{name:'Ram'},{name:'Sham'}];
Now, i need to create collection dynamically with 'mycollection' collection name. After that collection should like be:-
mycollection=> {name:Jack}, {name:Ram}, {name:Sham}
I know how to insert data by using Model.
Got a solution:
var thingSchema = new Schema({}, { strict: false, collection: 'mycollection' });
//strict, if true then values passed to our model constructor that were not specified in our schema do not get saved to the db.
//collection, for prevent from auto append 's'.
var Thing = mongoose.model('mycollection', thingSchema);
var thing = new Thing($arrayObj);
thing.save();
Say I have a collection that contains a field that references documents from another collection like follows:
ClassEnrollment
_id | student | class
---------------------
and classes in the Class collection have the following schema:
_id | className | teacher | building | time | days | classNumber | description
------------------------------------------------------------------------------
If I have a set of 3000 classes I want to populate on the server I might do something like ClassEnrollment.populate(listOfClassEnrollments, {path: 'class'});
In my situation, I don't want the majority of the class fields though, just the name. If I get the list of 3000 classes from the db with all fields, I end up taking a performance hit in the form of network latency (these 3000 classes have to be transferred from the hosted db to the server, which might be 50 MB of raw data if the descriptions are long)
Is there a way to populate the list of class enrollments with just the name through an option to populate (behind the scenes I imagine it would work like a projection, so the db just responds with the class name and _id instead of all the class information)?
You can use the select option in your populate call to do this:
ClassEnrollment.populate(listOfClassEnrollments, {path: 'class', select: 'className'});
To specify multiple fields, use a space-separated list:
ClassEnrollment.populate(
listOfClassEnrollments,
{path: 'class', select: 'className classNumber'}
);
Let's say we have a very simple user & video schemas.
1) USER SCHEMA
import mongoose from "mongoose";
const { Schema, model } = mongoose;
const UserSchema = new Schema({
name: String,
email: String,
password: String,
});
export default model("User", UserSchema);
2) VIDEOS SCHEMA
import mongoose from "mongoose";
const { Schema, model } = mongoose;
const { ObjectId } = Schema.Types;
const VideoSchema = new Schema({
videoOwnerId: { type: ObjectId, ref: "User", required: true },
title: { type: String, required: true },
desc: { type: String, required: true },
});
export default model("Video", VideoSchema);
Then I want to find in Videos Collection all videos by specific user AND at the same time all information about this user(a user document from Users Collection) and use projection on it ( select specific fields )
3) Somewhere in our code (maybe in a controller)
const videos = await Video.find({ videoOwnerId: "someId214121" }).populate("videoOwnerId", "-password");
So to populate with projection you use a populate("videoOwnerId", "-password") method, when the first argument is a field you want to populate, the second argument is a projection.
To get a document with all fields but without password for example
populate("videoOwnerId", "-password")
To get only specific fields that you want(string with fields separated by whitespace)
populate("videoOwnerId", "name email")