i would like to store a post as a document in mongodb. I’m using mongoose for modelling and the content is created by a user using a form. The content of the form is append to FormData and sending to server. This works so far. The only issue is, that empty fields, that are appended as empty strings in the req.body will be stored in the document. The minimalize-property of my dataschema is already set true …
const post = req.body;
await Post.create(post);
req.body looks like:
[Object: null prototype] {
image: '',
title: 'hi',
subtitle: '',
category: 'Jobs',
tags: '',
text: '',
contactperson: '',
contact: '',
author: 'Felicia',
expires: '2022-08-06'
}
My document looks exactly the same, but i would like to make it look like this:
{
title: 'hi',
category: 'Jobs',
author: 'Felicia',
expires: '2022-08-06'
}
Thanks so much for your help!
You could build an object by filtering the req.body empty properties with:
const post = {};
for (const key in req.body) {
const value = req.body[key];
if (value && value !== '') {
post[key] = value
}
}
await Post.create(post);
let post = {
image: '',
title: 'hi',
subtitle: '',
category: 'Jobs',
tags: undefined,
text: null,
contactperson: '',
contact: '',
author: 'Felicia',
expires: '2022-08-06'
};
let payload ={}
Object.keys(post).filter((key) => !!post[key] && (payload[key] = post[key]));
console.log(payload)
You could use the set method for Mongoose Schemas:
const mySchema = new mongoose.Schema(
{
myAttribute: {
type: String,
set: (attribute: string) => attribute === '' ? undefined : attribute,
},
},
{ strict: 'throw' },
);
This will unset the field if the string equals ''.
Use this to trim the strings:
set: (a: string) => a?.trim() === '' ? undefined : a
Related
I am trying to return the value of #microsoft.graph.downloadUrl from the json object below:
[
{
'#microsoft.graph.downloadUrl': 'https://public.bl.files.1drv.com/XXXX',
createdDateTime: '2021-07-10T06:14:31.03Z',
cTag: 'QQQQ',
eTag: 'SSSS',
id: 'FFFF',
lastModifiedDateTime: '2021-07-12T09:27:21.69Z',
name: 'FILE_NAME',
size: 98580,
webUrl: 'https://1drv.ms/b/SSSS',
reactions: { commentCount: 0 },
createdBy: { application: [Object], user: [Object] },
lastModifiedBy: { user: [Object] },
parentReference: {
driveId: 'XXX',
driveType: 'personal',
id: 'YYYY!YYY',
name: 'Documents',
path: '/drive/root:/Documents'
},
file: { mimeType: 'application/pdf', hashes: [Object] },
fileSystemInfo: {
createdDateTime: '2021-07-10T06:14:31.03Z',
lastModifiedDateTime: '2021-07-12T09:27:21.69Z'
}
}
]
I wish to use something like this that i had done to extract the name as I need to be able to get the #microsoft.graph.downloadUrl from each json object (known as f below) in 'files'.
var fileName = (JSON.stringify(files[f].name));
I tried both:
var fileURL = (JSON.stringify(files[f]."#microsoft.graph.downloadUrl"));
var fileURL = (JSON.stringify(files[f].#microsoft.graph.downloadUrl));
but neither work -- any help would be much appreciated!
You should just use files[f]["#microsoft.graph.downloadUrl"].
How can I transform from the old nested object array to the new flater one.
PLEASE NOTE: userId, quizId, and answerId are different values. They are strings and vary for each object in the array. So there are no issues of duplicates in the below before / after models
Model structure
const old = [{
userId: string,
quiz: [{
quizId: string,
createdAt: string,
completedAt: string,
answers: [{
answerId: string,
value: any,
updatedAt: string
}]
}]
}]
const new = [{
userId: string,
quizId: string,
createdAt: string,
completedAt: string,
responses: {
answerId: {
value: any,
updatedAt: string
}
}
}]
Each object in the array is unique on the composite key of userId quizId. In the old object the record has an array of answers whilst in the new object it has an object of responses the data contained within each is identical (answerId, value, updatedAt`) but the structure is of course different.
Current solution.
const allUniqueUserIds = [...new Set(refactoredQuizs.map(quiz => quiz.userId))]
const usersQuizDto: UsersQuizsDto[] = allUniqueUserIds.map((id) => {
const userQuizs = refactoredQuizs.filter(quiz => quiz.userId===id);
return {
RespondentID: id,
Quizs: userQuizs.map(quiz => {
return {
StartedAt: (quiz.createdAt as any)?.toDate()?.toUTCString(),
CompletedAt: (quiz.completedAt as any)?.toDate()?.toUTCString(),
UpdatedAt: '',
QuizId: quiz.quizId,
Answers: _.toPairs(quiz.responses).map(([answerId, { value, updatedAt }]) => {
return {
AnswerId: answerId,
Value: value,
UpdatedAt: (updatedAt as any)?.toDate()?.toUTCString()
}
})
}
})
}
});
I'm building app in Gatsby using Apollo to fetch and send data to CMS via GraphQL. All variables declared as Stringworks as expected but when I try to send an array of 5 objects, in console it gets empty array. What's interesting, when I try to do the same operation through Insomnia, GraphiQL app or even Apollo DevTools, all variables work.
Here's my query
const ADD_REVIEW = gql`
mutation AddReview(
$name: String!
$caption: String!
$shopifyId: String!
$rate: [Json!]
) {
createReview(
data: {
author: $name
caption: $caption
shopifyId: $shopifyId
rate: $rate
}
) {
id
author
caption
rate
shopifyId
}
}
`
here's array of objects I want to send through mutation
const [stars, setStars] = useState([
{
key: 1,
checked: true,
},
{
key: 2,
checked: true,
},
{
key: 3,
checked: true,
},
{
key: 4,
checked: false,
},
{
key: 5,
checked: false,
},
])
and here's submit function
const [addReview, { data }] = useMutation(ADD_REVIEW)
.
.
.
const handleSubmit = (e) => {
e.preventDefault()
let shopifyId = 'new id'
addReview({
variables: { name, caption, shopifyId, stars },
}).then((res) => console.log(res, data))
}
Does anyone know where I made mistake?
I want to populate answers(comments) on my post . But on populating it becomes null while before that it stores fine of storing Id's of answer.
My schema of post
var doubtsSchema = new mongoose.Schema({
title : String,
content : String,
tags : String,
created : {
type : Date,
default : Date.now},
author : {
id : {
type : mongoose.Schema.Types.ObjectId,
ref : "User"},
username : String},
answers : [{
type : mongoose.Schema.Types.ObjectId,
ref : "Answers"}]});
module.exports = mongoose.model("Doubts",doubtsSchema);
My schema of answer
var answersSchema = new mongoose.Schema({
content : String,
created : {
type : Date,
default : Date.now},
author : {
id : {
type : mongoose .Schema .Types . ObjectId,
ref : "User"},
username : String},
likes_count : Number});
module.exports = mongoose.model("Answers",answersSchema);
Populate is not working
Doubts.findById(req.params.id).populate('answers').exec(function(err,foundDoubt) {
if(err) {
console.log(err);
} else {
console.log("here");
console.log(foundDoubt);
res.render("doubts/show",{doubt : foundDoubt});
}
});
I made a simple example, it works
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/test", {useNewUrlParser: true});
const UserSchema = new mongoose.Schema({
name: String,
comments: [{type: mongoose.Schema.Types.ObjectId, ref: "Comments"}]
});
const CommentSchema = new mongoose.Schema({
content: ""
});
const Users = mongoose.model("Users", UserSchema);
const Comments = mongoose.model("Comments", CommentSchema);
// Adding data
Promise.all([
new Comments({content: "test 1"}).save(),
new Comments({content: "test 2"}).save(),
new Comments({content: "test 3"}).save()
]).then(result => {
result = result.map(r => r._id);
new Users({name: "test", comments: result}).save().then(user => {
// Getting with populate
Users.findById(user._id).populate("comments").then(console.log);
})
}).catch(console.error);
In console:
{ comments:
[ { _id: 5c979d9dedc0b1db90fe81dd, content: 'test 1', __v: 0 },
{ _id: 5c979d9dedc0b1db90fe81de, content: 'test 2', __v: 0 },
{ _id: 5c979d9dedc0b1db90fe81df, content: 'test 3', __v: 0 } ],
_id: 5c979d9dedc0b1db90fe81e0,
name: 'test',
__v: 0 }
Maybe it will help to find the error
I want to retrieve the form content on a submit and map that data into an object.
let userData = $(e.currentTarget).serializeArray();
let userDataObject = this.serializedToObject(userData);
--
Template objects to send through POST
serializedToObject(serializedArray) {
let templateObject = {
privider: '',
pop3: {
host: '',
port: 110,
ssl: false
},
imap: {
host: '',
port: 993
},
email: '',
password: ''
};
for (let data in serializedArray) {
}
return templateObject;
}
--
The form of the userData is
[Object, Object, Object, Object, Object, Object, Object]
-- While on object is of form
Object: {
name: 'provider',
value: 'Aladin'
}
Object: {
name: 'imap-host',
value: '955'
}
Object: {
name: 'imap-port',
value:
}
Object: {
email: 'test#gmail.com',
value:
}
So I need some help to map that array of objects to the templateObject.
AnyHelp will be highly appreciated.
Update
[{"name":"name","value":"Nicholas Barbaros"},{"name":"email","value":"george#google.com"},{"name":"password","value":"nicu121-mujik"},{"name":"imap","value":"imap.server.com"},{"name":"imap-port","value":"ad"},{"name":"pop3-host","value":"pop.server.com"},{"name":"pop3-port","value":"465"}, {"name":"pop3-ssl","value":"false"}]
The name-property of each serializedArray's object has a minus-character (-) representing nested objects, you can split by those characters and then set the values of your templateObject's properties:
var serializedArray = [{"name":"name","value":"Nicholas Barbaros"},{"name":"email","value":"george#google.com"},{"name":"password","value":"nicu121-mujik"},{"name":"imap","value":"imap.server.com"},{"name":"imap-port","value":"ad"},{"name":"pop3-host","value":"pop.server.com"},{"name":"pop3-port","value":"465"}, {"name":"pop3-ssl","value":"false"}];
// your defaults
var templateObject = {
provider: '',
pop3: {
host: '',
port: 110,
ssl: false
},
imap: {
host: '',
port: 993
},
email: '',
password: '',
};
serializedArray.forEach(function(obj) {
var deep = obj.name.split('-');
var key = deep.pop();
var level = templateObject;
deep.forEach(function(inner) {
var nested = level[inner];
var isObject = Object(nested) === nested;
level = isObject ? nested : {};
});
level[key] = obj.value;
});
// return templateObject; // when inside your function
console.log(templateObject);
You can also use reduce method, in a more functional way
const array = [{
name: 'provider',
value: 'Aladin'
},{
name: 'imap-host',
value: '955'
},{
name: 'imap-port',
value: 'something'
}];
const newObject = array.reduce( (acc, item, {}) => {
acc[item.name] = item.value;
return acc;
})
console.log(newObject);
Link to fiddle: https://jsfiddle.net/y5xkddnn/
There is too much overhead to iterate serialized array and map it to the nested object.
Please consider this approach, which is less complicated:
let userData = new FormData($(e.currentTarget)[0]);
let userDataObject = serializedToObject(userData);
function serializedToObject(data) {
return {
provider: data.get('provider'),
pop3: {
host: data.get('pop3-host'),
port: data.get('pop3-port'),
ssl: data.get('pop3-ssl')
},
imap: {
host: data.get('imap-host'),
port: data.get('imap-port')
},
email: data.get('email'),
password: data.get('password')
};
}
I guessed some fields here. Please correct them if needed.