save style for each field in database - node.js

I use mongodb and I have a model like this:
{
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
date: {
type: Date,
required: true,
},
}
I want to save styles (such as font, size, color, etc.) for each field
What is the best way to store them in a database?
Do I have to create a new field for each of them to store their style as a string (HTML code)?

You can create the list of css class like what bootstrap does. And then, you will create a new filed for each of them where you will just store the classes name.
all css will be stored in the css files
classes names associated to each elements will be stored in the database.
In that way, your app will be stay clean and you can reuse a lot of css class.

Related

use mongoose schema over multiple microservices

my application is split into multiple microservices that are running on heroku dynos (they can't access each others files). Sometimes, there are multiple microservices working with one collection. Therefore, both of the microservices need the according mongoose schema.
However, not both microservices need the full schema. For example, microservice A needs the full schema whereas microservice B only needs a few fields of that schema.
Example schema inside microservice A:
var AccountSchema = mongoose.Schema({
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
phone: { type: String, required: true, unique: true },
forename: { type: String, required: true },
surname: { type: String, required: true },
middleInitals: { type: String, required: false },
failedLoginAttempts: { type: Number, required: true, default: 0 },
lockUntil: { type: Number },
createdAt: { type: Date, default: Date.now }
})
Example Schema inside microservice B:
var AccountSchema = mongoose.Schema({
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
failedLoginAttempts: { type: Number, required: true, default: 0 },
lockUntil: { type: Number },
createdAt: { type: Date, default: Date.now }
})
My approach
I would just go ahead and create a new schema in each microservice, containing only the needed fields. However, I am not sure if there will be any problems when multiple microservices register a new schema to the MongoDB database? For example, both microservices would attempt to create an index for the unique field. Will there be any performance issues?
Does anybody have a different approach I could use? Is this even a valid approach to go with?
Thanks in advance :)
It's a valid approach. you can have 2 schemas pointing to the same collection. i have tested it and it works.
Mongoose is an Object Data Modeling (ODM) library, and you can have 2 objects looking at the same collection /(Table or view in SQL) - no problem with that.
No reason for performance problems, so long you got the right index. no relation to Object Data Modeling.
You might want to add some type key, so you can find only type1/type2 accounts on get request. On find, you can restrict getting the right fields with projection.
I think you should have only 2 keys in the index – email + password. If you have phone index and microservice B: don't include a phone –you will have a violation at the unique index of phone.
But if you really want a unique phone index you can make an override. You can generate temp unique value for phone for mircoservice B (using auto-Generated or duplicate the email value), you will ignore this value on mircoservice B and only find/ update / present phone in microsaervice A, where you have a valid phone. When user change from accountB type to accountA type – you must make sure to replace the wrong phone number with a valid one.
I see no problem in 2 schemas to same collection - you just need to mange your indexes the right way – to avoid collisions, and to insure you can differentiate the different accounts type in the collection.
As far as I can see there is no reason you simply can't use the same schema, maybe use some sort of privilege system and have it only return the right information between these separate micro services. You could have a fetch request tell it from which service its coming from and return a which items using a simple conditional.

What is the field type for a file in a Mongodb Schema/Model?

I'm using a Mongo Schema to post a form. Works well with all strings but now I'm trying to upload a file. What type of field should I specify the file would be in the Schema?
//create model/schema
const TrackSchema = new Schema({
title:{
type: String,
required: true
},
length:{
type: String,
required: true
},
available:{
type: Boolean,
required: true
},
image:{
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
source: {
type: **??,
required: true
}
})
What type should I make the 'source' field which will be a file coming from the form
It really depends on your use-case -- specifically with what constraints you are dealing with.
I can think of two ways of doing this:
Store it as a type: Buffer.
Store it as a type: String in base64.
Storing it as a Buffer may be the most efficient way to store it with regards to space/speed. It also gives you the flexibility to convert it to whatever type is needed for your use-case.
Storing it as a String will give you easier control of the file contents when you need to access it for downloading because you won't need to convert from Buffer to base64.
Personally I like to store files as a Bufferand tack on other necessary fields such as filename and mimetype which would yield something like:
source: {
file: { type: Buffer, required: true },
filename: { type: String, required: true },
mimetype: { type: String, required: true }
}
...but this is also specific to my use-cases.
There is also a 3rd option of storing it using GridFS in mongo in case your files exceed the 16MB filesize. You can read more about that in their official documentation page: https://docs.mongodb.com/manual/core/gridfs/
Typically, you store the file data to a database (if, at all, you're storing a file).
There are ways to store the file data.
Your file size is less than 16 MB. You can store the data directly to collection in buffer(Binary data).
source : { data: Buffer, contentType: String }
In case the file size is more than 16MB, you can use GridFS.
You store the file on disk and just store the path to mongodb collection. In this case, the type would just be string.

Sort Keys in Response Object from Mongoose in ExpressJS and NodeJS

I have been working on my own small API, so far everything works super fine, i just have a small cosmetic issue I can#t seem to find an answer to.
I defined a schema like so in mongoose:
const ArtistSchema = new Schema({
stageName: {
type: String,
unique: true,
required: true,
minlength: 3,
maxlength: 255
},
realName: {
type: String,
unique: true,
required: true,
minlength: 5,
maxlength: 255
},
birthday: {
type: Date,
required: true
},
debutDate: {
type: Date,
required: true
},
company: {
type: String,
minlength: 5,
maxlength: 255,
required: function () {
return this.active;
}
},
active: {
type: Boolean,
default: true
},
music: [AlbumSchema],
createdAt: {
type: Date,
default: Date.now
}
});
I can create an entry in the database, with no problem either. I use this function on app.post
create(req, res, next) {
const artistProps = req.body;
Artist.create(artistProps)
.then(artist => res.send(artist))
.catch(next);
},
This works good, but the res.send(artist)) actually returns the object with no key order.. or in a pattern I cannot recognize. I want the response to be the same sorting as i defined in the schema, beause now it returns it:
active, stagename, realname, label, music, birthday
while it should be stagename, realname, birthday, debutDate etc..
I hope someone can help me out here. I know i can sort the VALUEs of a specific key with sort (like sort stageName alphabetically) but I really cant find anything for the keys .
Express' res.send method recognizes that artist is an Object, and calls JSON.stringify on it to convert the Object to a JSON string before sending. Simplifying a bit, the JSON.stringify method iterates through your artist object keys in the order they were created. (Here's a link to the more complicated ordering explanation.) That explains the current behavior.
Others may chime in with their own proposals for how you might do what you're aiming for, but here's a simple one to try first:
First, do your own JSON.stringify, using a "replacer" to create
the output order that you want:
const artistString = JSON.stringify(artist, ["realName", "stageName", ...])
// '{"realName": "Paul David Hewson", "stageName": "Bono", ...}'
Then, use res.json(artistString), rather than res.send, to send your JSON string with the
correct Content-Type header. (res.send will assume you want
Content-Type: “text/html”.)
There are definitely more complicated approaches, including creating a function that gets keys, sorts them, and returns a replacer; or writing your own .toJSON() substitute for JSON.stringify. You may need to implement one of these approaches, because you have nested objects; the behavior of the replacer can be a bit wonky in this case. You might be able to list the nested properties immediately after the parent, like:
["realName", "type", ...]
but since you have the same names for some nested properties, this may or may not work for you. You might have to stringify the insides before you stringify the outsides (gah!).
In any case, hopefully my suggestion can be a first step.

Apostrophecms: Allow to upload PDF file only

I am having one field with relation. I want to upload only PDF files. Whereas I don't want to change the default setting for the dgad-attachments from app.js/default.js that allows all office type of files as those are needed in other places in project.
{
name: '_file',
type: 'joinByOne',
withType: 'apostrophe-file',
label: 'File',
required: true,
idField: 'fileId',
filters: {
projection: {
slug: 1,
title: 1,
attachment: 1
}
},
extensions: ['pdf'],
extensionMaps: {},
image: false
}
Can anyone help me on this please?
It sounds like you'll want to create a new file group in Apostrophe-attachments. You can use a file group to specify what types of files and/or extensions should be available when you add an apostrophe-attachments field to an object's schema. In order to add a file group that only contains PDFs, you will want to add this to the modules object in your app.js file:
'apostrophe-attachments': {
fileGroups: [
{
name: 'pdf',
label: 'Pdf',
extensions: ['pdf'],
image: false
}
]
}
This will create a new file group that will only allow files with the extension 'pdf'. Apostrophe-files isn't a regular schema type (it can't be added to an object's schema like other objects can). Instead of using apostrophe-files, it would be better to use apostrophe-attachments, which can be given a file group to restrict what types of files are allowed. In order to specify that group in your attachment, your new field will end up looking like this:
{
name: 'file',
type: 'attachment',
label: 'File',
group: 'pdf',
required: true
}
If you do decide you need to use a join directly to apostrophe-files, you will probably need to add some custom code in order to restrict the file type. If that is the case, you can find more information about apostrophe-files here:
https://apostrophecms.org/docs/modules/apostrophe-files/
You will probably be able to look at the way apostrophe-attachments handles file groups and replicate the behavior if necessary:
https://apostrophecms.org/docs/modules/apostrophe-attachments/

Sails.js & MongoDB: duplicate key error index

I'm using Sails.js (0.9.8) and MongoDB (via the sails-mongo adaptor) to create a collection of pages that can be positioned in a tree-view. I would like to store the path of a page in an array of UUIDs
My model:
module.exports = {
schema: true,
attributes: {
uuid: {
type: 'string',
unique: true,
required: true,
uuidv4: true
},
name: {
type: 'string',
required: true,
empty: false
},
path: {
type: 'array',
required: true,
array: true
}
}
}
It works well when I save a 'root' page (the 'path' property has just one item because it's a root page. Here is what it was saved in MongoDB:
{
_id: ObjectId("52f853e9609fb6c0341bdfcc"),
createdAt: ISODate("2014-02-10T04:22:01.828Z"),
name: "Home Page",
path: [
"a2b23e1f-954b-49a3-91f1-4d62d209a093"
],
updatedAt: ISODate("2014-02-10T04:22:01.833Z"),
uuid: "a2b23e1f-954b-49a3-91f1-4d62d209a093"
}
But when I want to create a 'subpage' below my previous created page (Home Page/Products), I get this error:
MongoError: E11000 duplicate key error index: cms-project.item.$path_1
dup key: { : "a2b23e1f-954b-49a3-91f1-4d62d209a093" }
Here is the data I sent:
{ name: 'Products',
uuid: 'a004ee54-7e42-49bf-976c-9bb93c118038',
path:
[ 'a2b23e1f-954b-49a3-91f1-4d62d209a093',
'a004ee54-7e42-49bf-976c-9bb93c118038' ] }
I probably missed something but I don't know what.
If I store the path in a string instead of an array, it work well, but I find it much less elegant and handy.
Not sure of all the Sails / Waterline parts myself as I've never played with it. But by the error the problem is there is a unique index on your array field.
When you are inserting your second document, you already have one of the values (the parent) in your path field in another document. The unique constraint is not going to allow this. Most certainly for what you are modelling, you do not want this and the index cannot be unique.
I hope that you set this up yourself under the assumption that it meant unique within the array contained in the document. If you did then you know where to look and what to change now. If this is being automatically deployed somehow, then I'm not the one to help.
Change the index to not be unique. You can confirm this through the mongo shell:
use cms-project
db.item.getIndices()
Good luck

Resources