I have such code where I can get new inserted doc id:
db.collection("cities").add({
name: "Tokyo",
country: "Japan"
})
.then(function(docRef) {
console.log("Document written with ID: ", docRef.id);
})
.catch(function(error) {
console.error("Error adding document: ", error);
});
Is it possible to get data from ref?
Yes you can do it like this:
.then(function(docRef) {
db.collection("cities").doc(docRef.id).get()
.then(snap => {
console.log('Here is the document you wrote to', snap.data()
})
})
Granted it requires another read which you probably didn't want
I found solution
static async createUserPofile(uid) {
const db = Firebase.firestore(),
date = Firebase.firestore.FieldValue.serverTimestamp(),
data ={
user_id: uid,
creation_time: date,
update_time: date
},
docRef = await db.collection("user_profiles").add(data),
get = await docRef.get();
return get.data();
}
We could retrieve added or updated data using this function:
function dataToObject(fDoc){
return { ...fDoc.data(), id: fDoc.id }}
We should chain 'get' method to retrieve added or updated firestore data:
let fDoc = await db.collection("cities").add({
name: "Tokyo",
country: "Japan"
}).get()
Use it to transform your snapshot to an object:
const upserData = dataToObject(fDoc)
Related
I'm executing an upsert mutation on MongoDB to create a new document or update an existing document. If the document exists, the mutation returns the id as expected. If a new document is created, the mutation returns null (in both Apollo sandbox and via console.log) in the initial return then in subsequent returns it will return the id. I need it to return the id of the newly created document immediately (on the first return) so I can use that id in subsequent actions.
Starting from the beginning here's the setup:
TYPEDEF
updateHourByEmployeeIdByJobDate(
jobDate: String
startTime: String
endTime: String
hoursWorked: String
employee: String
): Hour
RESOLVER
updateHourByEmployeeIdByJobDate: async (
parent,
{ jobDate, startTime, endTime, hoursWorked, employee },
context
) => {
// if (context.user) {
console.log("resolver hours update = ");
return Hour.findOneAndUpdate(
{ employee, jobDate },
{
jobDate,
startTime,
endTime,
hoursWorked,
employee,
},
{
upsert: true,
}
);
// }
// throw new AuthenticationError("You need to be logged in!");
},
MUTATION
//UPDATE HOUR RECORD - CREATES DOCUMENT IF IT DOESN'T EXIST OR UPDATES IF IT DOES EXIST VIA THE UPSERT OPTION ON THE RESOLVER
export const UPDATE_HOURS_BYEMPLOYEEID_BYJOBDATE = gql`
mutation UpdateHourByEmployeeIdByJobDate(
$jobDate: String
$startTime: String
$endTime: String
$hoursWorked: String
$employee: String
) {
updateHourByEmployeeIdByJobDate(
jobDate: $jobDate
startTime: $startTime
endTime: $endTime
hoursWorked: $hoursWorked
employee: $employee
) {
_id
}
}
`;
FRONT-END EXECUTION
const [ mostRecentHourUpdateId, setMostRecentHoursUpdateId ] = useState();
const [updateHours] = useMutation(UPDATE_HOURS_BYEMPLOYEEID_BYJOBDATE, {
onCompleted: (data) => {
console.log('mutation result #1 = ', data)
setMostRecentHoursUpdateId(data?.updateHourByEmployeeIdByJobDate?._id);
console.log('mutation result #2 = ', mostRecentHourUpdateId)
},
});
//section update database - this mutation is an upsert...it either updates or creates a record
const handleUpdateDatabase = async (data) => {
console.log(data);
try {
// eslint-disable-next-line
const { data2 } = await updateHours({
variables: {
jobDate: moment(data.date).format("MMMM DD YYYY"), //"January 20 2023"
startTime: `${data.startTime}:00 (MST)`, //"12:00:00 (MST)"
endTime: `${data.endTime}:00 (MST)`, //"13:00:00 (MST)"
hoursWorked: data.hours.toString(), //"3.0"
employee: userId, //"6398fb54494aa98f85992da3"
},
});
console.log('handle update database function = data = ', data2); //fix
} catch (err) {
console.error(err);
}
singleHoursRefetch();
};
I've tried using onComplete as part of the mutation request as well as useEffect not to mention running the mutation in Apollo Sandbox. Same result in all scenarios. The alternative is to re-run the useQuery to get the most recent / last record created but this seems like a challenging solution (if at some point the records are sorted differently) and/or seems like I should be able to get access to the newly created record immediately as part of the mutation results.
You'll want to use { returnNewDocument: true }
Like this:
const getData = async () => {
const returnedRecord = await Hour.findOneAndUpdate( { employee, jobDate }, { jobDate, startTime, endTime, hoursWorked, employee, }, { upsert: true, returnNewDocument: true } );
// do something with returnedRecord
}
getData();
For more information:
https://www.mongodb.com/docs/manual/reference/method/db.collection.findOneAndUpdate/
I am creating a MERN app and have a series of mongoose schema that are connected.
The hierarchy goes: Program -> Workout -> Exercise -> Set
Here is the model code for each Schema:
Program Schema
const programSchema = mongoose.Schema({
program_name:{
type: String,
},
workouts:[{
type: mongoose.Types.ObjectId,
ref: 'Workout'
}]
Workout Schema
const workoutSchema = mongoose.Schema({
workout_name:{
type:String
},
exercises: [{
type: mongoose.Types.ObjectId,
ref: 'Exercise'
}]
Exercise Schema
const exerciseSchema = mongoose.Schema({
exercise_name:{
type:String
},
notes:{
type:String
},
sets:[{
type: mongoose.Types.ObjectId,
ref: 'Set'
}]
Set Schema
const setSchema = mongoose.Schema({
weight:{
type: String
},
repetitions:{
type: String
},
rpe:{
type: String
}
My question is, now that they are all separate. How do I link a specific Set to a Exercise? or a specific Exercise to a Workout? etc. How do I reference them to each other so that I can create a whole program with various workouts, and each workout having various exercises, etc.
I would appreciate any wisdom. Thank you
For more info, here are the controllers.
Program Controller (CREATE NEW PROGRAM)
const createProgram = async (req, res) => {
//const {program_name, workouts} = req.body
try {
const program = new Program(req.body) // create a new program with the information requested
await program.save() // save it to database
res.status(201).send(program) // send it back to user
} catch (e) {
res.status(500).send(e)
}
WORKOUT CONTROLLER (CREATE NEW WORKOUT)
const createWorkout = async (req, res) => {
const {workout_name} = req.body
try {
const workout = await new Workout({
workout_name
})
await workout.save()
res.status(201).send(workout)
} catch(e) {
}
EXERCISE CONTROLLER (CREATE NEW EXERCISE)
const createExercise = async (req, res) => {
const { exercise_name='', notes='', sets } = req.body
try {
const exercise = await new Exercise({
exercise_name,
notes,
sets
})
await exercise.save()
res.status(201).send(exercise)
} catch (e) {
console.log(e)
}
SET CONTROLLER (CREATE NEW SET)
const createSet = async (req, res) => {
const {repetitions='', weight='', rpe=''} = req.body
try {
const set = await new Set({
weight,
repetitions,
rpe
})
await set.save()
res.status(201).send(set)
} catch (e) {
res.status(500).send(e)
}
The way I do it is on save I add the id to the attributed array. So i'll give you an example for one of your Routers then hopefully you can understand enough to do the rest.
For workouts you want to add it to a program when it's created. so when you create it, just add the id to the program you want to add it to.
Like so:
const {workout_name} = req.body
try {
const newWorkout = await Workout.create({
workout_name
})
Program.updateOne(
{ _id: req.params.ProgramId },
{ $addToSet: { workouts: newWorkout._id }},
)
res.status(201).send(workout)
} catch(e) {
}
So basically after creating your workout, you add that workout ID to the workouts array of the parent object. You would do the same for the rest of your Routers.
I want to get data that equals to question. For some reason it get everything out.
My Schema
userID: String,
questionAdd: [{
question: String,
answer: String,
}],
My code
var test2 = "What fast food chain has the most locations globally?";
await Data.findOne({
questionAdd: {
$elemMatch: {
question: {$regex: test2, $options: 'i'}
}
}
},(err, data)=>{
if(data){
var getData = data.toString();
console.log(getData);
}
})
Please help me!...
I have fix my code, i don't know there any way to get multi result in array object or not, but i change my Schema
userID: String,
question: String,
answer: String
my code after:
let messageArgs1 = args.join(' ');
var outString = messageArgs1.replace(/[`~!##$%^&()_|+\-=?;'",.<>\{\}\[\]\\\/]/gi, '');
var messageArgs2 = outString.toLowerCase();
var messageArgs = messageArgs2.toLowerCase();
if(messageArgs=="") return message.channel.send("Please type your question!");
await Data.find({
question:{$regex: messageArgs}
},{question: 1, answer: 1, _id:0}, (err, data)=>{
if(!data){
console.log(data);
return message.channel.send(`Nope!`);
}
else{
//do something
}
}).limit(9);
}
I currently have the following mongoose function in a hapi.js api call
server.route({
method: "PUT",
path:"/api/blockinfo/{hash}",
handler: async (request, h) => {
try{
var jsonPayload = JSON.parse(request.payload)
console.log(jsonPayload)
var result = await BlockModel.findOneAndUpdate(request.params.hash, {$set: { height : jsonPayload[Object.keys(jsonPayload)[0]]}}, {new: true});
return h.response(result);
}catch{
return h.response(error).code(500);
}
}
})
Its goal is basically to update a value using a PUT. In the case above, it will update the field height, and it will work just fine.
But what if I want to update an arbitrary field?
For example my object format is the following:
{"_id":"5cca9f15b1b535292eb4e468", "hash":"d6e0fdb404cb9779a34894b4809f492f1390216ef9d2dc0f2ec91f95cbfa89c9", "height":301651, "size":883, "time":1556782336, "__v":0}
In the case above I updated the height value using the $set, but what if I decide to input 2 random fields to update, for example, size and time.
This would be my put in postman:
{
"size": 300,
"time": 2
}
Well obviously it wont work in the code above because those fields are missing in the set.
SO how do i make that set to recognize automatically whatever it needs to update?
I tried to simplify it with the following code but it wont update anything
server.route({
method: "PUT",
path:"/api/blockinfo/{hash}",
handler: async (request, h) => {
try{
var result = await BlockModel.findOneAndUpdate(request.params.hash, request.payload, {new: true});
return h.response(result);
}catch{
return h.response(error).code(500);
}
}
})
Schema
const BlockModel = Mongoose.model("blocks", {
hash: String,
height: Number,
size: Number,
time: Number
});
Problem is with your hash key. First parameter/argument in findOneAndUpdate function should be the key value pair. And here you are directly putting the key.
So it should be
handler: async (request, h) => {
try {
const { hash } = request.params
var result = await BlockModel.findOneAndUpdate({ hash }, request.payload, { new: true })
return h.response(result)
} catch (err) {
return h.response(error).code(500)
}
}
Update:
You are defining mongoose model in incorrect way. Schema is not just an object. It should be mongoose object. Something like this
const schema = new Mongoose.Schema({
hash: String,
height: Number,
size: Number,
time: Number
})
export default Mongoose.model("blocks", schema)
handler: async (request, h) => {
try{
var result = await BlockModel.findOneAndUpdate(request.params.hash, JSON.parse(request.payload ), {new: true});
return h.response(result);
}catch{
return h.response(error).code(500);
}
}
SInce we are updating a JSON, the payload must be in JSON format
You have not added $set in your simplified code, adding that it should work.
Send payload as an object with the required fields.
server.route({
method: "PUT",
path:"/api/blockinfo/{hash}",
handler: async (request, h) => {
try{
var result = await BlockModel.findOneAndUpdate(request.params.hash, { $set: request.payload } , {new: true});
return h.response(result);
}catch{
return h.response(error).code(500);
}
}
})
I have this working fine with get.JSON but when I try and use the fetch API instead, it gives me the error "Required parameter: part".
export const fetchYoutube = () => {
return dispatch => {
fetchAsync()
.then(data => console.log(data))
.catch(reason => console.log(reason.message))
dispatch({
type: INCREMENT
})
}
}
async function fetchAsync () {
var query = {
part: 'snippet',
key: 'AIzaSyA3IHL73MF00WFjgxdwzg57nI1CwW4dybQ',
maxResults: 6,
type: 'video',
q: 'music'
}
let response = await fetch('https://www.googleapis.com/youtube/v3/search', {
data : query,
method: 'GET'
});
let data = await response.json();
return data;
}
How do I pass the query object using the fetch API?
Try attaching the query as params:
replace:
let response = await fetch('https://www.googleapis.com/youtube/v3/search', {
data : query,
method: 'GET'
});
with:
var url = new URL("https://www.googleapis.com/youtube/v3/search"),
query = {
part: 'snippet',
key: '#####################################',
maxResults: 6,
type: 'video',
q: 'music'
}
Object.keys(query).forEach(key => url.searchParams.append(key, query[key]))
let response = await fetch(url)
Setting query string using Fetch GET request