I have odata query:
/url/odata/ContractCards?
$top=20&
$count=true&
$filter=ContractId%20eq%2013ff820e-1ac7-ea11-a97d-899ae03249bd&
$orderby=LicenseType/Name%20asc&
$select=Id,ContractId,CardNumber,Name&
$expand=
Contract($select=ContractTypeCode,ContractVersionSetId),
ContractCardRightAssignments
($orderby=Right/Name%20asc;
$select=Id,ContractCardId,StartDate,EndDate,IsEstimatedStartDate,
IsEstimatedEndDate,IsInPerpetuity,RightId,Note,RunCount,RunCountNote,
IsRunCountUnlimited,HoldBackLength;
$expand=Right($select=Id,Name,TypeCode),
HoldbackType($select=Id,Name),
HoldbackFromRightGroup($select=Id,Name),
...
)
The result of the query is sorted by LicenseType.Name list of contractCards:
{
value:[
{
ContractCardName:"ContractCard1",
ContractCardRightAssignments:[{RightName:"Right1",StartDate:"2020-01-01"},{RightName:"Right2",StartDate:"2019-01-01"}],
LicenseType:{Name:"A license"}
},
{
ContractCardName:"ContractCard2",
ContractCardRightAssignments:[{RightName:"Right3",StartDate:"2019-01-01"},{RightName:"Right4",StartDate:"2018-01-01"}],
LicenseType:{Name:"B license"}
},
{
ContractCardName:"ContractCard3",
ContractCardRightAssignments:[{RightName:"Right3",StartDate:"2018-01-01"},{RightName:"Right4",StartDate:"2017-01-01"}],
LicenseType:{Name:"C license"}
}
]
}
I want to change sorting, to get the result sorted by min(StartDate) value, so the result should looks like(2017,2018,2019):
{
value:[
{
ContractCardName:"ContractCard3",
Rights:[{RightName:"Right3",StartDate:"2018-01-01"},{RightName:"Right4",StartDate:"2017-01-01"}],
LicenseType:{Name:"C license"}
},
{
ContractCardName:"ContractCard2",
Rights:[{RightName:"Right3",StartDate:"2019-01-01"},{RightName:"Right4",StartDate:"2018-01-01"}],
LicenseType:{Name:"B license"}
},
{
ContractCardName:"ContractCard1",
Rights:[{RightName:"Right1",StartDate:"2020-01-01"},{RightName:"Right2",StartDate:"2019-01-01"}],
LicenseType:{Name:"A license"}
}
]
}
I tried to change the query in part
$orderby=LicenseType/Name%20asc&
to something like
$orderby=ContractCardRightAssignments/StartDate.Min()%20asc
but no luck.
How to change the query to order the reault in a such way?
Related
I want to update the likes' value with 1.
My MongoDB structure is as follows .
{"_id":{"$oid":"5f980a66c4b0d52950bdf907"},
"course_id":"5002",
"lecture_id":"451",
"__v":0,
"created_at":{"$date":"2020-10-27T11:54:14.842Z"},
"message":[
{
"_id":{"$oid":"5f980a84c4b0d52950bdf90a"},
"from":{
"userId":"68819","name":"Developer IIRS",
"avatar":"https://api.adorable.io/avatars/285/811753.png"
},
"content":"ok",
"likes":0,
"parent_id":null,
"created_at":{"$date":"2020-10-27T11:54:44.388Z"}
}
]
}
Here is my code to update value of likes
router.post('/:lectureId/:courseId/:id', function(req, res, next) {
let query = {
lecture_id: req.params.lectureId,
course_id: req.params.courseId
};
let update = { $push: { message: { _id: req.params.id,likes: 1 } } }
var options = {
new: true
}
console.log('Liked', query)
Chat.update(query, update, function(err, result) {
if (err) {
//res.send(err);
console.log('err',err );
return err;
}
res.json(result);
})
});
Its basically adding new document. I am stuck here how can i do this.
"lecture_id": "451",
"course_id": "5002"
},
{
$inc: {
"message.$[elem].likes": 1
}
},
{
new: true,
arrayFilters: [
{
"elem._id": "5f980a84c4b0d52950bdf90a"
}
]
})```
Here is the mongo query.
db.collection.update({
"lecture_id": "451",
"course_id": "5002",
"message._id": "5f980a84c4b0d52950bdf91a"
},
{
"$inc": {
"message.$.likes": 1
}
})
Try it here Mongo Playground
Not an expert in nodejs. Below update statement may work for you.
let update = { $inc: { "message.$.likes": 1 } }
Hell devs, Here is my document schema
var Schema = mongoose.Schema;
var botSchema = new Schema({
Bot_name: String,
UserName:String,
Modules: [{
ModuleStatement: String,
ModuleID: String,
ModuleResponse: [{
Response: String,
TransBotID: String
}]
}]
});
what i want to do is update the ModuleStatement as well as push the element into ModuleResponse setting Response and TransBotID to some values
I tried following but it only updates the ModuleStatement and doesn't push element into ModuleResponse
botSchema.update({ 'Modules.ModuleID': req.body.ModId }, { '$set': { 'Modules.$.ModuleStatement': req.body.Statement } }, function (err, data) {
if (err) {
throw err;
} else {
botSchema.update({ "Modules.ModuleID": req.body.ModId }, { "$push": { "ModuleResponse": { "Response": req.body.Statement, "TransBotID": req.body.transitmod } } }, function (err, data) {
if (err) {
throw err;
}
else {
res.json('upgraded');
}
})
}
})
how can i push element into ModuleResponse while setting the ModuleStatement at the same time?
$push is only available in the $group stage. You may want to try as the following:
botSchema.find({'Modules.ModuleID': req.body.ModId}, (err, bots) => {
if (err) {
throw err;
} else {
bots.forEach((bot) => {
bot.modules.forEach((botModule) => {
if (botModule.ModuleID == req.body.ModId) {
botModule.Statement = req.body.Statement;
botModule.ModuleResponse.push({
Response: req.body.Statement,
TransBotID: req.body.transitmod
})
}
});
bot.save((err, data) => {
if (err) throw err;
});
});
res.json('upgraded');
}
})
Here you have a shell code:
db.bot.update(
{ "Modules.ModuleID": "<some_id>" },
{
"$set": { "Modules.$.ModuleStatement": "<some_statement>" },
"$push": {
"Modules.$.ModuleResponse": {
"Response" : "<some_response>",
"TransBotID" : "<some_trans_id>"
}
}
}
)
The thing is that you can have more than one update expressions in one update document. I believe you can convert it to mongoose quite easily.
i am trying to create a new multidimensional array from the data i am getting from 3rd part API.
"output":[
{
"is_indb":false,
"name":"adam",
"tokens":29
},
{
"is_indb":true,
"name":"aaron",
"tokens":2,
},
{
"is_indb":false,
"name":"adam",
"tokens":3,
},
{
"is_indb":false,
"name":"axel",
"tokens":5,
},
{
"is_indb":false,
"name":"andy",
"tokens":5,
},
{
"is_indb":false,
"name":"bob",
"tokens":5,
},
{
"is_indb":false,
"name":"aldo",
"tokens":5,
},
{
"is_indb":false,
"name":"julia",
"tokens":5,
}
]
i would like to create a new array and fill it with data from response.
but i would like to do some pre checks like
take only those whose, is_indb = false
take only those whose, name starts with a
so the final array will be, all those whosse is_indb = true and name starts with a
var newaray = [[adam,29],[adam,3],[axel,5],[andy,5],[aldo,5]];
so far i have tried using _pluck and getting some weird outputs. i am able to get sible elements using _pluck but cant get multiple items.
i can think of logic like this
var newaray = [];
if( (_pluck(msg.output,'is_indb') == false && ((_pluck(msg.output,'name').substring(0, 1) == "a")){
newaray.push( [ _.pluck(msg.output, 'name') , _.pluck(msg.output, 'token')] );
}
Use filter and map:
var filteredOutput = output
.filter(function(elem) {
// The return statement should return true,
// if you want the element to pass into the new array.
return elem.is_indb === false && typeof elem.name === "string" && elem.name.indexOf('a') === 0;
})
.map(function(elem) {
return [elem.name, elem.tokens];
});
or with ES6:
let filteredOutput = output
.filter(elem => elem.is_indb === false && typeof elem.name === "string" && elem.name.indexOf('a') === 0)
.map(elem => [elem.name, elem.tokens])
with ES6 and using regex (inspired by Peter Grainger's answer, but also case insensitive):
let filteredOutput = output
.filter(elem => elem.is_indb === false && /^a/i.test(elem.name))
.map(elem => [elem.name, elem.tokens])
and by the way, what you posted is an array of objects, not a multidimensional array, which is an array of arrays.
You could use a filter then a map?
const output = [
{
"is_indb":false,
"name":"adam",
"tokens":29
},
{
"is_indb":true,
"name":"aaron",
"tokens":2,
},
{
"is_indb":false,
"name":"adam",
"tokens":3,
},
{
"is_indb":false,
"name":"axel",
"tokens":5,
},
{
"is_indb":false,
"name":"andy",
"tokens":5,
},
{
"is_indb":false,
"name":"bob",
"tokens":5,
},
{
"is_indb":false,
"name":"aldo",
"tokens":5,
},
{
"is_indb":false,
"name":"julia",
"tokens":5,
}
]
const transform = output.filter(value => /^a/.test(value.name) && !value.is_indb)
.map(value => [value.name, value.tokens])
console.log(transform)
You can use _.filter and get the output in this form
op = [{ obj1 } ,{obj2}];
but as you want to remove some keys also then you can use _.pick
var op = _.filter(ip , function(obj){
if(obj.is_indb == false && obj.name[0] == 'a'){
return true;
}
else{
return false;
}
})
//so now you have all the entries filtered out
var opAltered = _.pick(op,['name','tokens']);
//you will get this result
/*
opAltered = [
{
name : <something>,
tokens : <something>
},{
...
}
]
*/
or If you want array you can use this
opAltered = _.map(op,['name','tokens'];
I have used more code to make you understand properly you can reduce it once you understand Thanks.
So, I have a function which should be executed in case that a if condition is true. I simply do not know how to implement it in a method. I have the following code:
Meteor.methods({
'popItems': function () {
var date = new Date().getTime();
if ( "check if this.userId && any item in the array 'itemIds' is $gt date" ) {
userManagement.update({
'_id': this.userId
}, {
$pop: {'itemIds': -1}
}
}
);
};
}
});
So, in case the if condition is true, the $pop function should be executed. In case false, it should not. I wrote this for the if clause, but it doesn't work:
if (this.userId && userManagement.find({
'itemIds': {$gt: date}})) {...$pop function...}
Meteor.methods({
'popItems': function () {
var date = new Date().getTime();
if (this.userId && userManagement.find({'itemIds':{ $gt: date}}).count() > 0 ) {
userManagement.update({
'_id': this.userId
}, {
$pop: {'itemIds': -1}
});
}
};
});
Include the query in the update operation as
Meteor.methods({
'popItems': function () {
var date = new Date();
userManagement.update(
{
'_id': this.userId,
'itemIds': { '$gt': date }
},
{ '$pop': { 'itemIds': -1 } }
);
}
});
I've made some assumptions in coming up with the above solution. The first one being itemIds is an array composed of just Date objects e.g.
itemIds: [
ISODate("2017-01-25T06:20:00.000Z"),
ISODate("2017-01-26T06:20:00.000Z"),
ISODate("2017-01-27T06:20:00.000Z"),
...
ISODate("2017-02-25T06:20:00.000Z")
]
The above query in the update operation can also be specified with an $and operator as:
Meteor.methods({
'popItems': function () {
var date = new Date();
userManagement.update(
{
'$and': [
{ '_id': this.userId },
{ 'itemIds': { '$gt': date } },
]
},
{ '$pop': { 'itemIds': -1 } }
);
}
});
I'm trying to find a specific ID in my document and then merge an array to the existing one, for example if I have this array stored in db.friends:
["12","13","14"]
and I send this array: ["12","16","18"], db.friends should contain: ["12","13","14","16","18"]
I'm using underscore library, but I'm not sure I have to (maybe "aggregate" in mongoose?)
Here is what I did, can you tell me where am I wrong?
function saveFollowers(req, res) {
var friends = req.body.friends; // the new array to merge ["54aafe9df4ee360300fc94c7"];
User.findOne({_id: req.user._id}).exec(function (err, user) {
if (err) {
res.jsonp({error: "Error fetching user info"})
} else {
friends = _.extend(friends, user.friends); //user.friends=existing friends we have in db
user.save(function (err) {
if (err) { res.jsonp({error: "Cant save"}); }
console.log("Friends NOW:"+JSON.stringify(friends)); //Here I don't see the merge, also, I can't see it in mongo db.
res.jsonp("success");
});
}
});
Thank you!
With your current implementation, you haven't actually modified the friends key in the returned user object. So rather you can use the union method as
user.friends = _.union(friends, user.friends); //user.friends=existing friends
user.save(function (err) { .. }
Or with ES6 using the spread operator for concatenating the array and Set for creating a distinct set of elements:
user.friends = [...new Set([...friends ,...user.friends])];
user.save(function (err) { .. }
Another alternative is using the aggregation framework, you could utilize the $setUnion operator:
function saveFollowers(req, res) {
var friends = req.body.friends; // the new array to merge ["54aafe9df4ee360300fc94c7"];
User.aggregate([
{ "$match": { _id: req.user._id } },
{
"$project": {
"friends": { "$setUnion": [ "$friends", friends ] }
}
}
]).exec(function (err, results){
if (err) {
res.jsonp({error: "Error fetching user info"})
} else {
User.findByIdAndUpdate(req.user._id,
{ "$set": { "friends": results[0].friends } },
{ "new": true },
function (err, user) {
if (err) { res.jsonp({error: "Cant save"}); }
console.log("Friends NOW: "+ JSON.stringify(user.friends));
res.jsonp("success");
}
);
}
});
}