i'm coding an application using AngularJS, NodeJS and Mongoose.
Now, i'm doing a chart and I need to return some data passsing some parameters.
But the aggregation does not work. I have this query working in MongoDB:
var user = db.getCollection('users').find(
{profile: "SUPERVISOR"},{_id: 1}).map(function(u){return u._id;}
)
db.getCollection("visitas").aggregate(
{ '$match':
{ createdAt:
{ '$gte': ISODate('2015-01-10T00:00:00.000Z'),
'$lt': ISODate('2015-07-01T00:00:00.000Z') } } }, { '$group':
{ _id: { usuario: user, dia: [Object] },
visitas: { '$sum': 1 } } }
)
When I try to run the same query in my application using Mongoose, the query does not work. The problem i've seen is that the comma between MATCH and GROUP is disapearing. When i try to search with only group or match, the query works. Someone can help me? This is the application code:
.then(function (listaUsuarios){
var argsVisit;
console.log({ $match : { "createdAt" : { $gte: "2015-01-10T00:00:00.000Z", $lt: "2015-07-01T00:00:00.000Z" }} },
{ $group : { _id : { "usuario" : listaUsuarios , "dia" : { $dayOfMonth : "$createdAt" } }, "visitas" : { $sum : 1 } } });
Visita.aggregate({ $match : { "createdAt" : { $gte: "2015-01-10T00:00:00.000Z", $lt: "2015-07-01T00:00:00.000Z" }} },
{ $group : { _id : { "usuario" : listaUsuarios , "dia" : { $dayOfMonth : "$createdAt" } }, "visitas" : { $sum : 1 } } })
.exec(function (err, results) {
if (err) {
console.log("Erro!!!");
deferredDados.reject({
error: 500,
message: 'Erro buscando Visita, erro: '+err
});
} else {
if (!results || results.length == 0) {
console.log("Sem retorno!!!");
deferredDados.resolve( [0,0,0,0,0,0,0] ); //Tudo zerado poruqe não há retorno.
//deferredDados.resolve(0);
deferredDados.reject({
error: 500,
message: 'Erro buscando Visitas, não achou resultados'
});
} else {
console.log("Dados"+results);
deferredDados.resolve( results );
//deferredDados.resolve( results.data] );
}
}
});
return deferredDados.promise;
})
SOLVED!!!
A member of my team found the error! \o/
Maybe this can help someone who will have the same problem.
To solve, you just have to convert the date, in string, to the date type.
The solved code is below:
.then(function (listaUsuarios){
var argsVisit;
if (tipoVisita == 'N'){
argsVisit = {'user' : { "$in" :listaUsuarios }, 'tipo' : { "$in" : ["2001","2002"] }, "createdAt": {"$gte": dataInicial, "$lt": dataFinal }};
} else if (tipoVisita == 'R'){
argsVisit = {'user' : { "$in" :listaUsuarios }, 'tipo' : { "$in" : ["2005"] }, "createdAt": {"$gte": dataInicial, "$lt": dataFinal }};
} else if (tipoVisita == 'I'){
argsVisit = {'user' : { "$in" :listaUsuarios }, 'tipo' : { "$in" : ["2003"] }, "createdAt": {"$gte": dataInicial, "$lt": dataFinal }};
}
var initDate = new Date('2015-04-02T00:00:00.000Z');
var endDate = new Date('2015-05-09T00:00:00.000Z');
argsMatch = [{ $match : { "createdAt" : { $gte: initDate, $lt: endDate }} },
{ $group : { _id : { "usuario" : listaUsuarios , "dia" : { $dayOfMonth : "$createdAt" } }, "visitas" : {$sum : { $cond: [ {$or : [ { $eq: [ "$tipo", "2001"] },{ $eq: [ "$tipo","2002"] }] },1,0 ]}}}
}]
Visita.aggregate(argsMatch)
.exec(function (err, results) {
if (err) {
console.log("Erro!!!");
deferredDados.reject({
error: 500,
message: 'Erro buscando Visita, erro: '+err
});
} else {
if (!results || results.length == 0) {
console.log("Sem retorno!!!");
deferredDados.resolve( [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] ); //Tudo zerado poruqe não há retorno.
//deferredDados.resolve(0);
deferredDados.reject({
error: 500,
message: 'Erro buscando Visitas, não achou resultados'
});
} else {
deferredDados.resolve( results );
}
}
});
return deferredDados.promise;
})
.then(function(dados) {
res.json(dados);
})
.catch(function(fallback) {
console.log('Erro no retorno dos usuarios!!!');
console.log(fallback);
});
I hope this can help someone.
Related
This is my first stack overflow question, and I'm excited to hear your thoughts.
> db.travelers.find().pretty()
{
"_id" : ObjectId("615e3ddece93c870aca4e465"),
"assembly" : [
{
"_id" : ObjectId("615e3ddece93c870aca4e466"),
"SN" : 24,
"Model" : "J240",
"Job" : 1234,
"Revision" : "A",
"Version" : 1
}
],
"assyHistory" : [ ],
"subAssemblies" : [
{
"_id" : ObjectId("615e3deace93c870aca4e467"),
"SN" : 19,
"Model" : "P500"
}
I am trying to delete the nested data in "subAssemblies" by its id. My current route:
router.delete("/subassembly/:id", deleteOneSubassembly);
my current controller:
deleteOneSubassembly: async (req, res) => {
try {
const removeOne = await Traveler.deleteOne({
_id: req.params.id
});
console.log(removeOne);
res.json(removeOne);
} catch (err) {
res.send({ error: err });
}
}
And all I keep getting back is:
"n": 0,
"nModified": 0,
"ok": 1
Wondering where I might be going wrong?
use update and $pull the item
const removeOne = await Traveler.updateOne(
{
"subAssemblies._id": req.params.id
},
{
"$pull": { subAssemblies: { _id: req.params.id }
}
});
aggregate
db.collection.update({
"subAssemblies._id": ObjectId("615e3deace93c870aca4e467")
},
{
$pull: {
subAssemblies: {
_id: ObjectId("615e3deace93c870aca4e467")
}
}
})
mongoplayground
Sample data: there are multiple similar collection:
{
"_id" : NumberLong(301),
"telecom" : [
{
"countryCode" : {
"value" : "+1"
},
"extension" : [
{
"url" : "primary",
"value" : [
"true"
]
}
],
"modifiedValue" : {
"value" : "8887778888"
},
"system" : {
"value" : "phone"
},
"useCode" : {
"value" : "Home Phone"
},
"value" : {
"value" : "8887778888"
}
},
{
"extension" : [
{
"url" : "primary",
"value" : [
"true"
]
}
],
"modifiedValue" : {
"value" : "abc#test.com"
},
"system" : {
"value" : "email"
},
"useCode" : {
"value" : "work"
},
"value" : {
"value" : "abc#test.com"
}
}
]
}
Issue: I want to cont the collection where telecom.system.value = email and countryCode doesn't exist in the email part object. here I am attaching a script but I need one line query
var count = 0,i;
db.getCollection('practitioner').find({"telecom.system.value":"email"}).forEach(function(practitioner){
//print("updating : " +practitioner._id.valueOf())
telecom = practitioner.telecom.valueOf()
for(i= 0;i<telecom.length;i++){
if(telecom[i].system.value === 'email' && telecom[i].countryCode){
count+=1;
}
}
});
print(" Total count of the practitioner with country code in email object: "+count)
Above mention, the script is working fine and the output is as I expected. but the script is not optimised and I want to write in a single line query. Thanks in advance.
You can try aggregation method aggregate(),
Approach 1:
$match condition for countryCode should exists and system.value should be email
$filter to iterate loop of telecom array and check both condition, this will return expected elements
$size to get total element from above filter result
$group by null and count total
var result = await db.getCollection('practitioner').aggregate([
{
$match: {
telecom: {
$elemMatch: {
countryCode: { $exists: true },
"system.value": "email"
}
}
}
},
{
$project: {
count: {
$size: {
$filter: {
input: "$telecom",
cond: {
$and: [
{ $ne: [{ $type: "$$this.countryCode" }, "missing"] },
{ $eq: ["$$this.system.value", "email"] }
]
}
}
}
}
}
},
{
$group: {
_id: null,
count: { $sum: "$count" }
}
}
]);
print("Total count of the practitioner with country code in email object: "+result[0].count);
Playground
Approach 2:
$match condition for countryCode should exists and system.value should be email
$unwind deconstruct telecom array
$match to filter document using above conditions
$count to get total elements count
var result = await db.getCollection('practitioner').aggregate([
{
$match: {
telecom: {
$elemMatch: {
countryCode: { $exists: true },
"system.value": "email"
}
}
}
},
{ $unwind: "$telecom" },
{
$match: {
"telecom.countryCode": { $exists: true },
"telecom.system.value": "email"
}
},
{ $count: "count" }
]);
print("Total count of the practitioner with country code in email object: "+result[0].count);
Playground
I have not tested the performance but you can check and use as per your requirement.
firebase rules
{
"rules": {
"ingredients": {
".read": true,
".write": true,
},
"orders": {
".read": "auth != null",
".write": "auth != null",
".indexOn": ["userId"]
}
}
}
firebase data
{
"ingredients" : {
"bacon" : 0,
"cheese" : 0,
"meat" : 0,
"salad" : 0
},
"orders" : {
"-M-gRBK60ImmEg55J2lC" : {
"ingredients" : {
"bacon" : 0,
"cheese" : 0,
"meat" : 1,
"salad" : 1
},
"orderData" : {
"country" : "a",
"deliveryMethod" : "fastest",
"email" : "a#a.com",
"name" : "a",
"street" : "aa",
"zipcode" : "11111"
},
"price" : 1.8,
"userId" : "LyKBp44aSgPiGPdKvClUNtddJ7G3"
}
}
}
here i want to retrieve orders from firebase and filter it according to userId
to display user specific orders
but it fails and console.log(res.data) give me empty obj { }
instead of the orders .. there's no error message
.. what is the problem here ??
export const fetchOrders = (token, userId) => {
return dispatch => {
dispatch(fetchOrdersStart()); // to set loading to true
const queryParams = '?auth=' + token + '&orderBy="userId"&equalTo="' + userId + '"';
axios.get( '/orders.json' + queryParams)
.then( res => {
console.log(res.data);
const fetchedOrders = [];
for ( let key in res.data ) {
fetchedOrders.push( {
...res.data[key],
id: key
} );
}
dispatch(fetchOrdersSuccess(fetchedOrders));
} )
.catch( err => {
dispatch(fetchOrdersFail(err));
} );
};
};
How can I get the output in tree structure by matching the parent? I can only use a single ng-repeat to display this.
My expected output
firstname :-dsfsdf
lastname :- fdsfsdfs
account:
role:-dsfsdf
status:-dsfdfsfds
js
var app = angular.module("test",[]);
app.controller("MainCtrl",function($scope){
$scope.inputs = [
{
"firstname" : "Test"
},{
"lastname" : "Test1"
},{
"Account" : [
{"role" : "Test3"},
{"status" : "Test4"},
]
},
{
"Account1" : [
{"role" : "Test3"},
{"status" : "Test4"},
]
},
{
"Account2" : [
{"role" : {
'dim3': {
'dim4':{
'dim5':'cccc'
}
}
}
},
{"status" : "Test4"},
{"status" : "Test4"},
]
},
{
"ending" : "yes"
}
];
/*$scope.person = [];*/
$scope.myPersonObj = [];
$scope.checkIndex1 = function(arg, myPersonObj)
{
if (angular.isArray(arg) || angular.isObject(arg)) {
angular.forEach(arg, function (value, key) {
console.log(value + "started");
if(angular.isObject(value) || angular.isArray(value))
{
$scope.checkIndex1(value, myPersonObj);
}
else
{
console.log( value + "pushing--test");
myPersonObj.push(arg);
}
});
}
else
{
console.log( value + "pushing1");
myPersonObj.push(arg);
}
}
$scope.checkIndex1($scope.inputs, $scope.myPersonObj);
console.log("myPersonObj :"+ JSON.stringify($scope.myPersonObj));
console.log($scope.inputs[2] + "del");
}):
I have a [user] document stored that contains a nested sub-array [profiles],[favorites]. I am simply trying to delete($pull) a favorites from a given profile based on the favorites name.
{
"_id" : ObjectId("558d53eebdd9804820090fa1"),
"name" : "Frank",
"email" : "Frank#FrankTheTank.com",
"profiles" : [
{
"avatar" : "div-male",
"age" : "35",
"gender" : "Male",
"profilename" : "Oly Lifter",
"_id" : ObjectId("558d5404bdd9804820090fa2"),
"favorites" : [
{
"name" : "Power Clean"
},
{
"name" : "Hang Clean"
},
{
"name" : "Clean and Jerk"
}
],
"createdAt" : ISODate("2015-06-26T13:30:44.661Z")
}
],
"createdAt" : ISODate("2015-06-26T13:30:22.884Z"),
"role" : "user",
"__v" : 0
}
Using a MongoDB IDE robomongo, I'm able to successfully remove a favorite item from a known User and Profile ID using this
db.users.update($find: {
'profiles': {
'profiles._id': ObjectId("558d5404bdd9804820090fa2")
},
{
$pull: {
'profiles.$.favorites': {
'name': 'Hang Clean'
}
}
})
However, when I call from my server API using the following syntax, I receive an error, note req.body._id = "558d5404bdd9804820090fa2" and req.body.favorites.name = "Hang Clean"
User.findByIdAndUpdate(_user._id, {
'profiles._id': req.body._id
}, {
$pull: {
'profiles.$.favorites': {
'name': req.body.favorites.name
}
}
}, {
safe: true,
upsert: true
},
function(err, model) {
if (err) {
console.log(err);
return res.status(500).send('Error Deleting Profile');
}
return res.status(200).send('Profile Deleted!');
});
Try updating using the findOneAndUpdate() method since you are supplying the findByIdAndUpdate() method with the wrong parameters: the second argument { 'profiles._id': req.body._id } should be part of the first query object hence you need to use the findOneAndUpdate() method as follows, making sure you convert the string ids into ObjectId's:
var mongoose = require('mongoose');
var id = mongoose.Types.ObjectId(_user._id),
profileId = mongoose.Types.ObjectId(req.body._id),
query = {
"_id": id,
"profiles._id": profileId
},
update = {
"$pull": {
"profiles.$.favorites": { "name": req.body.favorites.name }
}
},
options = { "multi": true, "upsert": true };
User.findOneAndUpdate(query, update, options, function(err, model) {
if(err){
console.log(err);
return res.status(500).send('Error Deleting Profile');
}
return res.status(200).send('Profile Deleted!');
});