I am having a hard time understanding serverTimestamp in firestore.
When I save a document in database in a firebase function using Fieldvalue.serverTimestamp() or in a javascript client code using serverTimestamp() it sometimes doesn't save the same thing in the database.
See screenshots below :
Sometime I get an object with {nanoseconds: xxx, seconds: xxx} and sometimes I get a timestamp formatted date...
The problem is when I try to query my orders using query(collectionRefOrders, orderBy('createdAt', 'desc'), limit(10)).
The orders with the object appears before the others ones even if they are created after...
Any clue why this happens ? What am I doing wrong ?
Thanks a lot.
EDIT :
Here is the code I use to add documents in the my firebase function (it is a request function I call in a website) :
const { getFirestore, FieldValue } = require('firebase-admin/firestore');
const firebaseDB = getFirestore();
exports.createOrderFromTunnel = functions.region('europe-west3')
.runWith({
timeoutSeconds: 10,
memory: "4GB",
})
.https
.onRequest(async (req, res) => {
cors(req, res, async () => {
try {
const { apiKey } = req.body;
const project = await getProjectFromApiKey(apiKey);
if (!project) {
return res.json({
success: false,
error: 'Unauthorized: invalid or missing api key'
});
}
const contactData = {
address: {},
createdAt: FieldValue.serverTimestamp()
};
const orderData = {
accounting: {
totalHT: 0,
totalTTC: 0,
totalTVA: 0,
},
createdAt: FieldValue.serverTimestamp(),
status: 'NEW',
};
const refProject = firebaseDB
.collection('projects')
.doc(project.id);
const colOrder = firebaseDB.collection(`projects/${project.id}/orders`)
const refOrder = colOrder.doc();
const colContact = firebaseDB.collection(`projects/${project.id}/contacts`)
const refContact = colContact.doc();
await firebaseDB.runTransaction(async transaction => {
const snapProject = await transaction.get(refProject);
const dataProject = snapProject.data();
const sequenceContact = dataProject.sequenceContact;
const sequenceOrder = dataProject.sequenceOrder;
contactData.sequence = sequenceContact;
orderData.sequenceNumber = sequenceOrder;
await transaction.set(refContact, contactData);
orderData.customer.id = refContact.id;
orderData.customer.sequence = sequenceContact;
await transaction.set(refOrder, orderData);
await transaction.update(refProject, {
sequenceContact: sequenceContact + 1,
sequenceOrder: sequenceOrder + 1,
totalContacts: dataProject.totalContacts + 1,
totalOrders: dataProject.totalOrders + 1,
});
return refOrder.id;
});
return res.json({
success: true
});
} catch (err) {
functions.logger.error(err);
return res.json({
success: false,
err
});
}
});
});
Here is the code I use to add documents in my client code (it is a web app in javascript) :
const createOrder = async (projectId) => {
try {
const orderData = {
accounting: {
totalHT: 0,
totalTTC: 0,
totalTVA: 0,
},
createdAt: serverTimestamp(),
status: 'NEW',
surface: 0,
};
const refProject = doc(firebaseDB, 'projects', projectId);
const colOrder = collection(firebaseDB, `projects/${projectId}/orders`)
const refOrder = doc(colOrder);
return await runTransaction(firebaseDB, async (transaction) => {
const snapProject = await transaction.get(refProject);
if (!snapProject.exists()) {
throw "Document does not exist!";
}
const dataProject = snapProject.data();
const sequence = dataProject.sequenceOrder;
orderData.sequenceNumber = sequence;
transaction.set(refOrder, orderData);
transaction.update(refProject, { sequenceOrder: sequence + 1, totalOrders: dataProject.totalOrders + 1 });
return refOrder.id;
});
} catch (e) {
console.error(e);
return null;
}
};
Related
While hitting API I'm getting function from my services/ElasticSearch.js and for some reason function there is not working after the axios part.
In the below file I've called function elasticService.updateDocument this function has been brought from another file.
'''
class ProductController {
constructor() { }
async saveProduct(req, res) {
console.log('ITs coming here')
let { _id, Product } = req.body;
if (_id) delete req.body._id;
let elasticResult;
try {
if (Product && Product.Category) {
req.body.Category = Product.Category
delete Product.Category
}
if (Product && Product.URL) {
const exists = await ProductService.checkProductByUrl(Product.URL);
_id = exists._id
}
const result = await ProductService.saveProduct(req.body, _id);
if (result) {
if (_id) {
console.log('Here.... UPDATE')
const savedProduct = await ProductModel.createPayload(req.body);
console.log(savedProduct,'saved_product')
let elaticDoc = await this.createElasticDocData(savedProduct);
console.log(elaticDoc.id,'elasticResult')
elaticDoc.id = result._id;
elaticDoc = new Elastic(elaticDoc);
console.log(elaticDoc,'<----------elaticdoc-------------->')
elasticResult = await elasticService.updateDocument(JSON.stringify(elaticDoc), req.body.Category)
console.log(elasticResult,'elasticResult')
}
else {
console.log('Here.... ADD')
const savedProduct = await ProductModel.createPayload(result);
let elaticDoc = await this.createElasticDocData(savedProduct);
elaticDoc.id = result._id;
elaticDoc = new Elastic(elaticDoc);
elasticResult = await elasticService.createDocument(JSON.stringify(elaticDoc), req.body.Category)
}
const response = new Response(1, "Product is saved successfully", "", "", { product: result, elasticResult: elasticResult });
return res.status(200).send(response);
}
const response = new Response(0, "Error in saving Product", 0, "Product not saved", {});
return res.status(200).send(response);
} catch (error) {
const response = new Response(0, "Unexpected Error", 0, error, {});
return res.status(400).send(response);
}
}
'''
This is the elasticappsearch file where above mentioned is coming from and for some reason it's not working after axios.patch part.
'''
const private_key = process.env.elastic_private_key
const search_key = process.env.elastic_search_key
const axios = require("axios")
class ElasticAppSearch {
async updateDocument(body, engine) {
console.log('Its coming in updateDOCS here')
const response = await axios.patch(`${process.env.elastic_url}/${engine}/documents`, body, {
headers: {
Authorization: `Bearer ${private_key}`,
},
});
console.log(response,'<--===-=-=-=-=-=-=-=-=-=-=-=-response')
return response.data
}
'''
I am making a simple Firestore pagination.
When it goes forward works as expected, but when it should go backwards it always goes to the first record.
I have been stuck here for a while, even crammed both (forward and backward) in the same function to ease the debugging.
Edit:
Added simplified version (still the same undesired results):
async init() {
const result = await (await firestore())
.collection('documents')
.limit(this.limit)
.orderBy('createTimestamp')
// .orderBy('userName')
.get()
console.log(result)
this.lastVisible = result.docs[result.docs.length - 1]
;[this.firstVisible] = result.docs
result.forEach(doc => {
console.log('doc', doc.data())
this.myDocuments.push(doc)
})
},
async forward() {
const result = await (await firestore())
.collection('documents')
.orderBy('createTimestamp')
// .orderBy('userName')
.startAfter(this.lastVisible)
.limit(this.limit)
.get()
this.lastVisible = result.docs[result.docs.length - 1]
;[this.firstVisible] = result.docs
if (result.empty === false)
result.forEach(doc => {
console.log('doc', doc.data())
this.myDocuments.push(doc)
})
},
async backward() {
const result = await (await firestore())
.collection('documents')
.orderBy('createTimestamp')
// .orderBy('userName')
.endBefore(this.lastVisible)
.limit(this.limit)
.get()
this.lastVisible = result.docs[result.docs.length - 1]
;[this.firstVisible] = result.docs
if (result.empty === false)
result.forEach(doc => {
console.log('doc', doc.data())
this.myDocuments.push(doc)
})
},
Added the calling method:
getAllDocuments: async ({ rootState, commit }, payload) => {
const documentsDb = new DocumentsDB(`${rootState.authentication.user.id}`)
console.log('Get all documents(admin)')
console.log('payload :>> ', payload)
const { startAt, endBefore, constraints, limit } = payload
console.log('startAt :>> ', startAt)
console.log('endBefore :>> ', endBefore)
console.log('limit :>> ', limit)
const documents = await documentsDb.readWithPagination(constraints, startAt, endBefore, limit)
console.log('documents', documents)
// const documents = await documentsDb.readAllAsAdmin()
// console.log('documents: ', documents)
commit('setDocuments', documents) },
I left the console.log() for debuging reasons.
payload :>> {constraints: null, endBefore: "2UxB7Z1HWCmvkEcfLZ5H", startAt: null, limit: 5}constraints: nullendBefore: "2UxB7Z1HWCmvkEcfLZ5H"limit: 5startAt: null__proto__: Object
Thhe original code
async readWithPagination(constraints = null, startAt = null, endBefore = null, limit = null) {
const collectionRef = (await firestore()).collection(this.collectionPath)
let query = collectionRef
if (limit) query = query.limit(limit)
query.orderBy('createTimestamp')
if (constraints) {
constraints.forEach(constraint => {
query = query.where(...constraint)
})
}
query = query.orderBy(firebase.firestore.FieldPath.documentId())
if (startAt) {
query = query.startAfter(startAt)
}
if (endBefore) {
query = query.endBefore(endBefore)
console.log('query :>> ', query)
}
const formatResult = result =>
result.docs.map(ref =>
this.convertObjectTimestampPropertiesToDate({
id: ref.id,
...ref.data(),
})
)
return query.get().then(formatResult) }
Edit as requested in comments:
dispatchPaginatedForwardDocuments(startAt = null) {
const payload = {}
payload.orderBy = [['createTimestamp', 'asc']]
payload.constraints = [['status', '==', 4]]
payload.limit = this.limit
payload.startAt = startAt?.id || null
this.$store.dispatch('admin/getPaginatedForwardDocuments', payload, { root: true })
},
dispatchPaginatedPrevDocuments() {
const payload = {}
payload.orderBy = [['createTimestamp', 'asc']]
payload.constraints = [['status', '==', 4]]
payload.limit = this.limit
payload.startAt = this.lastDocument.id
payload.endBefore = this.firstDocument.id
this.$store.dispatch('admin/getPaginatedBackwardsDocuments', payload, { root: true })
},
And this:
import UserDocumentsDB from '#/firebase/user-documents-db'
// import UsersDB from '#/firebase/users-db'
import DocumentsDB from '#/firebase/documents-db'
import { storage } from 'firebase'
export default {
// Fetch documents with pagination forwards and constraints
// This works as expected
getPaginatedForwardDocuments: async ({ rootState, commit }, payload) => {
const documentsDb = new DocumentsDB(`${rootState.authentication.user.id}`)
const documents = await documentsDb.readPaginatedForward(payload)
console.log('documents: ', documents)
commit('setDocuments', documents)
},
// Fetch documents with pagination backwards and constraints
getPaginatedBackwardsDocuments: async ({ rootState, commit }, payload) => {
console.log('getPaginatedBackwardsDocuments', payload)
const documentsDb = new DocumentsDB(`${rootState.authentication.user.id}`)
const documents = await documentsDb.readPaginatedBackwards(payload)
console.log('documents: ', documents)
commit('setDocuments', documents)
},
For certain types of messages, I want to target users by FIRTokens vs topic, which are stored in my real-time database. I load these tokens with async/await and then decide if I want to send notifications to a topic vs a smaller list of users. The data loading code works as expected. But what's odd is that if I use .sendMulticast(payload), the notifications fail for all tokens in the list. On the other hand if I use .sendToDevice(adminFIRTokens, payload) the notification goes successfully to all my users. Right now my list has 2 tokens and with sendMulticast I have 2 failures and with sendToDevice I have 2 successes. Am I missing the point of what sendMulticast is supposed to do? According to the docs: Send messages to multiple devices:
The REST API and the Admin FCM APIs allow you to multicast a message to a list of device registration tokens. You can specify up to 500 device registration tokens per invocation.
So both should logically work. Then why does one fail and the other work? In fact with sendToDevice I get a multicastId in the response!
Here are some console outputs:
sendToDevice:
Sent filtered message notification successfully:
{
results:
[
{ messageId: '0:1...45' },
{ messageId: '16...55' }
],
canonicalRegistrationTokenCount: 0,
failureCount: 0,
successCount: 2,
multicastId: 3008...7000
}
sendMulticast:
List of tokens that caused failures: dJP03n-RC_Y:...MvPkTbuV,fDo1S8jPbCM:...2YETyXef
Cloud function to send the notification:
functions.database
.ref("/discussionMessages/{autoId}/")
.onCreate(async (snapshot, context) => {
// console.log("Snapshot: ", snapshot);
try {
const groupsRef = admin.database().ref("people/groups");
const adminUsersRef = groupsRef.child("admin");
const filteredUsersRef = groupsRef.child("filtered");
const filteredUsersSnapshot = await filteredUsersRef.once("value");
const adminUsersSnapshot = await adminUsersRef.once("value");
var adminUsersFIRTokens = {};
var filteredUsersFIRTokens = {};
if (filteredUsersSnapshot.exists()) {
filteredUsersFIRTokens = filteredUsersSnapshot.val();
}
if (adminUsersSnapshot.exists()) {
adminUsersFIRTokens = adminUsersSnapshot.val();
}
const topicName = "SpeechDrillDiscussions";
const message = snapshot.val();
const senderName = message.userName;
const senderCountry = message.userCountryEmoji;
const title = senderName + " " + senderCountry;
const messageText = message.message;
const messageTimestamp = message.messageTimestamp.toString();
const messageID = message.hasOwnProperty("messageID")
? message.messageID
: undefined;
const senderEmailId = message.userEmailAddress;
const senderUserName = getUserNameFromEmail(senderEmailId);
const isSenderFiltered = filteredUsersFIRTokens.hasOwnProperty(
senderUserName
);
var payload = {
notification: {
title: title,
body: messageText,
sound: "default",
},
data: {
messageID: messageID,
messageTimestamp: messageTimestamp,
},
};
if (isSenderFiltered) {
adminFIRTokens = Object.values(adminUsersFIRTokens);
// payload.tokens = adminFIRTokens; //Needed for sendMulticast
return (
admin
.messaging()
.sendToDevice(adminFIRTokens, payload)
// .sendMulticast(payload)
.then(function (response) {
if (response.failureCount === 0) {
console.log(
"Sent filtered message notification successfully:",
response
);
} else {
console.log(
"Sending filtered message notification failed for some tokens:",
response
);
}
// if (response.failureCount > 0) {
// const failedTokens = [];
// response.responses.forEach((resp, idx) => {
// if (!resp.success) {
// failedTokens.push(adminFIRTokens[idx]);
// }
// });
// console.log(
// "List of tokens that caused failures: " + failedTokens
// );
// }
return true;
})
);
} else {
payload.topic = topicName;
return admin
.messaging()
.send(payload)
.then(function (response) {
console.log("Notification sent successfully:", response);
return true;
});
}
} catch (error) {
console.log("Notification sent failed:", error);
return false;
}
});
I think it's an issue of using a different payload structure.
This is the old one (without iOS specific info):
var payload = {
notification: {
title: title,
body: messageText,
sound: "default",
},
data: {
messageID: messageID,
messageTimestamp: messageTimestamp,
},
};
Whereas this is the new version (apns has iOS specific info)
var payload = {
notification: {
title: title,
body: messageText,
},
data: {
messageID: messageID,
messageTimestamp: messageTimestamp,
},
apns: {
payload: {
aps: {
sound: "default",
},
},
},
};
With the new structure, both send and sendMulticast are working properly. Which would fail to send or give errors like apns key is not supported in payload.
The new function:
functions.database
.ref("/discussionMessages/{autoId}/")
.onCreate(async (snapshot, context) => {
// console.log("Snapshot: ", snapshot);
try {
const groupsRef = admin.database().ref("people/groups");
const adminUsersRef = groupsRef.child("admin");
const filteredUsersRef = groupsRef.child("filtered");
const filteredUsersSnapshot = await filteredUsersRef.once("value");
const adminUsersSnapshot = await adminUsersRef.once("value");
var adminUsersFIRTokens = {};
var filteredUsersFIRTokens = {};
if (filteredUsersSnapshot.exists()) {
filteredUsersFIRTokens = filteredUsersSnapshot.val();
}
if (adminUsersSnapshot.exists()) {
adminUsersFIRTokens = adminUsersSnapshot.val();
}
// console.log(
// "Admin and Filtered Users: ",
// adminUsersFIRTokens,
// " ",
// filteredUsersFIRTokens
// );
const topicName = "SpeechDrillDiscussions";
const message = snapshot.val();
// console.log("Received new message: ", message);
const senderName = message.userName;
const senderCountry = message.userCountryEmoji;
const title = senderName + " " + senderCountry;
const messageText = message.message;
const messageTimestamp = message.messageTimestamp.toString();
const messageID = message.hasOwnProperty("messageID")
? message.messageID
: undefined;
const senderEmailId = message.userEmailAddress;
const senderUserName = getUserNameFromEmail(senderEmailId);
const isSenderFiltered = filteredUsersFIRTokens.hasOwnProperty(
senderUserName
);
console.log(
"Will attempt to send notification for message with message id: ",
messageID
);
var payload = {
notification: {
title: title,
body: messageText,
},
data: {
messageID: messageID,
messageTimestamp: messageTimestamp,
},
apns: {
payload: {
aps: {
sound: "default",
},
},
},
};
console.log("Is sender filtered? ", isSenderFiltered);
if (isSenderFiltered) {
adminFIRTokens = Object.values(adminUsersFIRTokens);
console.log("Sending filtered notification with sendMulticast()");
payload.tokens = adminFIRTokens; //Needed for sendMulticast
return admin
.messaging()
.sendMulticast(payload)
.then((response) => {
console.log(
"Sent filtered message (using sendMulticast) notification: ",
JSON.stringify(response)
);
if (response.failureCount > 0) {
const failedTokens = [];
response.responses.forEach((resp, idx) => {
if (!resp.success) {
failedTokens.push(adminFIRTokens[idx]);
}
});
console.log(
"List of tokens that caused failures: " + failedTokens
);
}
return true;
});
} else {
console.log("Sending topic message with send()");
payload.topic = topicName;
return admin
.messaging()
.send(payload)
.then((response) => {
console.log(
"Sent topic message (using send) notification: ",
JSON.stringify(response)
);
return true;
});
}
} catch (error) {
console.log("Notification sent failed:", error);
return false;
}
});
what I expect to happen:
when the user clicks addProject button the event listener will run calling
formSubmit
and we will check for the date if it's valid or not then if it's valid it will call fetchingCompanyNameAndUserData
it will fetch the required data update the state and it will call checkUniqueName which again will fetch some data making sure there is no duplication and then it's supposed to call this.insert()
which will finally insert the data into our firestore-NoSQL- DB.
The issue:
these function specially the checkUniqueName keeps calling it self over and over and I don't know what is wrong there.
the code:
formSubmit = event => {
event.preventDefault();
const isLoading = this.state;
var sdate = this.state.projectData.sdate;
var edate = this.state.projectData.edate;
if (sdate > edate) {
NotificationManager.error(`Please entre a valid dates`);
return;
} else {
// isLoading = true;
this.fetchingCompanyNameAndUserData();
}
};
fetchingCompanyNameAndUserData = async () => {
const userRef = fireStore.collection('users');
const userData = await userRef.where("Email", "==", auth.currentUser.email).get();
userData.forEach(doc => {
console.log('this one must match', doc.data().CompanyName)
const cashedFirstName = doc.data().FirstName;
const cashedLastName = doc.data().LastName;
const fullName = cashedFirstName + ' ' + cashedLastName;
return this.setState({
companyName: doc.data().CompanyName,
userName: fullName,
}, () => {
console.log('done fetching');
this.checkUniqueName();
});
})
};
checkUniqueName = async () => {
const projectName = this.state.projectData.title;
const companyName = this.state.companyName;
const projectRef = fireStore.collection('PROJECT')
const projectData = await projectRef.where("ProjectName", "==", projectName).get();
projectData.forEach(doc => {
if (doc.data().CompanyName !== companyName) {
console.log('checking unique nameing');
this.insert();
} else {
NotificationManager.error('this project already exists');
}
})
}
async insert() {
//async function foo() {
console.log('insreting proooo');
var ptitle = this.state.projectData.title;
var pdesc = this.state.projectData.desc;
var sdate = this.state.projectData.sdate;
var edate = this.state.projectData.edate;
var status = this.state.projectData.status;
var companyName = this.state.companyName;
try {
let response = await fireStore.collection("PROJECT").add(
{
ProjectName: ptitle,
CompanyName: companyName,
ProjectDescription: pdesc,
startDate: sdate,
EndDate: edate,
Status: status,
CreatedBy: auth.currentUser.email,
CreatedDate: toUTCDateString(new Date()),
LastModifiedBy: auth.currentUser.email,
LastModifiedDate: toUTCDateString(new Date()),
UserDocId: auth.currentUser.uid
});
let doc = await fireStore.collection("PROJECT").doc(response.id).get()
this.handleClose();
//alert(doc.id)
var d1 = doc.id;
this.props.history.push('/app/dashboard/addproject/' + d1);
//this.handleClose;
NotificationManager.success('Project Created Successfully!');
}
catch (error) {
//console.log('error: ', error);
console.log(error)
}
}
Hope I made it as clear as possible here
Your checkUniqueName() function can be rewritten as:
checkUniqueName = async () => {
const projectName = this.state.projectData.title;
const companyName = this.state.companyName;
const projectRef = fireStore.collection('PROJECT')
const qsMatchingProjects = await projectRef.where("ProjectName", "==", projectName).where("CompanyName", "==", companyName).get();
if (qsMatchingProjects.empty) {
this.insert();
} else {
NotificationManager.error('this project already exists');
}
}
forgive me the question.
I'm not used to node and sync / await
I have the following function which queries a mongodb returning a json, I'm saving that return on redis.
So far so good.
findLightnings: async (request, h) => {
const q = request.query.q.split(':');
const index = q[0];
const value = q[1].split(',');
const dateInit = new Date(request.query.dateInit);
const dateEnd = new Date(request.query.dateEnd);
const page = request.query.page;
const distance = request.query.distance;
const redis = require('redis');
const client = redis.createClient();
let limit = 300;
let filter = {
$and: [{
data: {
$gte: dateInit.toISOString(),
$lte: dateEnd.toISOString()
}
}]
}
if (index === 'latlng') {
filter['$and'][0]['geo.coordinates'] = {
$near: {
$geometry: {
type: 'Point',
coordinates: value.map(Number),
$minDistance: 0,
$maxDistance: distance
}
}
}
limit = 100;
} else {
filter['$and'][0][`cidade.${index}`] = {
$in: value
}
}
return client.get('elektro', async (err, reply) => {
let resp = null;
if (reply) {
console.log(reply); //<<<<<<<< Return Json OK
resp = reply // <<<<<<<<<< Return TRUE in json's place
} else {
console.log('db')
const query = await Lightning.find(filter).sort('data').skip(page*limit).limit(limit).exec();
client.set('elektro', JSON.stringify(query));
client.expire('elektro', 3600);
resp = query
}
return JSON.stringify(resp);
})
}
The problem is time to recover this data from the redis.
In the console log json appears normal, how much tento returns that value for the main function it comes 'TRUE' and not the json saved in redis.
Someone can give me a helping hand on this.
I really need this function.
const redis = require('redis');
const client = redis.createClient(6379);
const bluebird = require("bluebird");
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);
const redisdata = await client.getAsync("user:photos");
if (redisdata) {
console.log(`cache EXISTS`)
return res.json({ source: 'cache', data: JSON.parse(redisdata) })
}
I was able to solve the problem with the redis client.getAsync().
which already has a native async function:
source: Node-redis
The final code is as follows:
findLightnings: async (request, h) => {
const q = request.query.q.split(':');
const index = q[0];
const value = q[1].split(',');
const dateInit = new Date(request.query.dateInit);
const dateEnd = new Date(request.query.dateEnd);
const page = request.query.page;
const distance = request.query.distance;
let limit = 300;
let filter = {
$and: [{
data: {
$gte: dateInit.toISOString(),
$lte: dateEnd.toISOString()
}
}]
}
if (index === 'latlng') {
filter['$and'][0]['geo.coordinates'] = {
$near: {
$geometry: {
type: 'Point',
coordinates: value.map(Number),
$minDistance: 0,
$maxDistance: distance
}
}
}
limit = 100;
} else {
filter['$and'][0][`cidade.${index}`] = {
$in: value
}
}
return getAsync('findLightnings'+ '/' + request.query.q + '/' + request.query.dateInit + '/' + request.query.dateEnd).then(async (res) => {
if(res){
console.log('Fonte Dados => redis')
return res
}else{
console.log('Fonte Dados => db')
try {
const query = await Lightning.find(filter).sort('data').exec();//.skip(page*limit).limit(limit).exec();
client.set('findLightnings'+ '/' + request.query.q + '/' + request.query.dateInit + '/' + request.query.dateEnd, JSON.stringify(query));
return query;
} catch (err) {
return Boom.badData(err);
}
}
client.close();
});
},