I have to select matched casts item [m_credits_cast] from the Movie collection by using Regex value.
Movie Modal
var mongoose = require('mongoose');
var movieSchema = new mongoose.Schema({
m_tmdb_id: {
type: Number,
unique: true,
index: true
},
m_original_title: {
type: String
},
m_poster_path: {
type: String
},
m_credits_cast: {
type: Array
},
m_release_date: {
type: Date
},
m_title: {
type: String
},
created_at: {
type: Date
},
updated_at: {
type: Date,
default: Date.now
}
});
var MovieModel = mongoose.model('Movie', movieSchema);
module.exports = {
movie: MovieModel
}
Js code
router.post('/casts', function(req, res, next) {
var searchText = req.body.searchtext;
var regexValue = '^' + searchText;
Movie
.aggregate([{
$match: {
'm_credits_cast.name': { '$regex': regexValue, '$options': 'i' }
}
},
{
$project: {
m_credits_cast: {
$filter: {
input: '$m_credits_cast',
as: 'cast',
cond: { $eq: ['$$cast.name', { '$regex': regexValue, '$options': 'i' }] }
}
},
_id: 0
}
}
])
.exec(function(err, casts) {
return res.status(500).json(casts);
}).catch(function(error) {
return res.status(500).json(error);
});
});
The code is not working because i am using $regex inside $project operator.How can i resolve this issue?
Movie Collection
[{
"_id": "5913e96548f1956df16f33a0",
"m_tmdb_id": 401246,
"m_original_title": "The Square",
"m_poster_path": "/g7ifEh3XBKftVA0g1zz9lXORm7l.jpg",
"m_release_date": "2017-08-25T00:00:00.000Z",
"m_runtime": 142,
"m_credits_cast": [{
"cast_id": 2,
"character": "Christian",
"credit_id": "575823d9c3a3687d6f00157f",
"gender": 2,
"id": 150802,
"name": "Claes Bang",
"order": 0,
"profile_path": "/iwPu7hwSj6A9BkO9M13SDkhD7QE.jpg"
},
{
"cast_id": 0,
"character": "Anne",
"credit_id": "575823bec3a3687d6a0016cf",
"gender": 1,
"id": 32798,
"name": "Elisabeth Moss",
"order": 1,
"profile_path": "/iSp2t9GYUUgyqTpz25J6hOHH2An.jpg"
}
],
"m_genres": [{
"id": 18,
"name": "Drama"
}]
}, {
"_id": "5840ebceb386b78c69b56602",
"m_tmdb_id": 336000,
"m_original_title": "The Glass Castle",
"m_poster_path": "/d5fLQ9ZMa1jZ2mODCv5lOWJDugX.jpg",
"m_release_date": "2017-08-11T00:00:00.000Z",
"m_runtime": 0,
"m_credits_cast": [{
"cast_id": 6,
"character": "Jeannette Walls",
"credit_id": "574fbcc6c3a3687950000f7c",
"gender": 1,
"id": 60073,
"name": "Brie Larson",
"order": 1,
"profile_path": "/p66rOUPo1ZFZ7XrAKZ6DjdsvCA2.jpg"
},
{
"cast_id": 7,
"character": "Rose Mary Walls",
"credit_id": "574fbcddc3a36879430011ff",
"gender": 1,
"id": 3489,
"name": "Naomi Watts",
"order": 2,
"profile_path": "/8W02WOJI1pEGh2iqQsgITR5tV0P.jpg"
},
{
"cast_id": 30,
"character": "Miss Bivens",
"credit_id": "58e3d04a925141281902086e",
"gender": 1,
"id": 43259,
"name": "Kyra Harper",
"order": 19,
"profile_path": "/hItQl4CyIC6Www5FQeHVWrv76ap.jpg"
},
{
"cast_id": 31,
"character": "Jeannette Walls (Age 5 and 6)",
"credit_id": "58e3d063c3a36872af01ecaf",
"gender": 0,
"id": 1505453,
"name": "Chandler Head",
"order": 20,
"profile_path": null
},
{
"cast_id": 32,
"character": "Intern",
"credit_id": "58e3d070925141281902089c",
"gender": 0,
"id": 1652138,
"name": "Hamza Haq",
"order": 21,
"profile_path": null
}
],
"m_genres": [{
"id": 18,
"name": "Drama"
}]
}]
Related
I have an aggregation pipeline which supposed to return an ordered array. However. Every time I make an API cal, it returns a different order each time. Here is my code
exports.getResultToCompetition = asyncHandler(async (req, res, next) => {
const data = await Result.aggregate([
{
$match: { competition: mongoose.Types.ObjectId(req.params.competitionId) },
},
{
$project: {
points: 1,
kilogramms: 1,
sector: 1,
user: 1,
competition: 1,
place: 1,
},
},
{
$sort: {
kilogramms: -1,
},
},
{
$lookup: {
from: "users", // must be the PHYSICAL name of the collection
localField: "user",
foreignField: "_id",
as: "user",
},
},
{
$addFields: {
user: {
$arrayElemAt: ["$user", 0],
},
},
},
{
$group: {
_id: "$sector",
res: {
$push: "$$ROOT",
},
},
},
]);
res.status(200).json({ success: true, data });
});
And the Schema:
const mongoose = require('mongoose');
const ResultSchema = new mongoose.Schema({
competitionSeries: {
type: String,
default: 0,
},
points: {
type: Number,
default: 0,
},
sector: {
type: String,
},
kilogramms: {
type: Number,
default: 0,
},
place: {
type: Number,
default: 0,
},
isCompetitionRunning: {
type: Boolean,
default: true,
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true,
},
team: {
name: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
partner: {
type: String,
},
teamName: {
type: String,
},
},
competition: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Competition',
required: true,
},
});
module.exports = Result = mongoose.model('Result', ResultSchema);
The kilograms field is saved as a Double in the MongoDB database
I set the value in the frontend in React as a number.
I am not sure if its causing the problem.
The kilograms value supposed to be a float number like 14.5
This is the result which is correct:
{
"success": true,
"data": [
{
"_id": "B",
"res": [
{
"_id": "5eca12e2607c2c0017c16904",
"points": 1,
"kilogramms": 90.52,
"place": 59,
"sector": "B",
"competition": "5eb90caa7b45620017a4d919",
"user": {
"_id": "5eb82c89e5d6cc0017e71a2a",
"avatar": "placeholder.jpg",
"role": "user"
}
},
{
"_id": "5eca1406607c2c0017c16918",
"points": 2,
"kilogramms": 39.45,
"place": 10,
"sector": "B",
"competition": "5eb90caa7b45620017a4d919",
"user": {
"_id": "5eb83175e5d6cc0017e71a42",
"avatar": "653571a228226499806e8a717cf2d6e1",
"role": "user"
}
},
{
"_id": "5eca11fc607c2c0017c168f5",
"points": 3,
"kilogramms": 29.62,
"place": 8,
"sector": "B",
"competition": "5eb90caa7b45620017a4d919",
"user": {
"_id": "5eb83970e5d6cc0017e71a64",
"avatar": "1589316331809-feederuser",
"role": "user"
}
},
{
"_id": "5eca1250607c2c0017c168fa",
"points": 4,
"kilogramms": 24.25,
"place": 56,
"sector": "B",
"competition": "5eb90caa7b45620017a4d919",
"user": {
"_id": "5eb83a00e5d6cc0017e71a67",
"avatar": "placeholder.jpg",
"role": "user"
}
}
]
},
{
"_id": "C",
"res": [
{
"_id": "5eca12cc607c2c0017c16903",
"points": 1,
"kilogramms": 72.43,
"place": 52,
"sector": "C",
"competition": "5eb90caa7b45620017a4d919",
"user": {
"_id": "5eb83c2ee5d6cc0017e71a70",
"avatar": "56065850e67a64878e5034d06cecc0ea",
"role": "user"
}
},
{
"_id": "5eca1307607c2c0017c16907",
"points": 2,
"kilogramms": 43.35,
"place": 12,
"sector": "C",
"competition": "5eb90caa7b45620017a4d919",
"user": {
"_id": "5eb998864d62090017231ce6",
"avatar": "placeholder.jpg",
"role": "user",
"name": "Halász Tibor"
}
},
{
"_id": "5eca1325607c2c0017c16909",
"points": 3,
"kilogramms": 39.43,
"place": 15,
"sector": "C",
"competition": "5eb90caa7b45620017a4d919",
"user": {
"_id": "5eb9b46c4d62090017231cf8",
"avatar": "placeholder.jpg",
"role": "user"
}
},
{
"_id": "5eca14c1607c2c0017c16927",
"points": 4,
"kilogramms": 36.99,
"place": 11,
"sector": "C",
"competition": "5eb90caa7b45620017a4d919",
"user": {
"_id": "5eb82fdbe5d6cc0017e71a3d",
"avatar": "placeholder.jpg",
"role": "user"
}
}
]
}
]
}
After I call again the endpoint it shows a different order. Meaning, Sector C is coming first which is not correct because in Sector B there is a higher kilograms result.
You can add a maxKilogramm field to your documents, and sort by that field by adding the following stages to the end of your aggregation.
{
$addFields: {
"maxKilogramm": {
$max: "$res.kilogramms"
}
}
},
{
$sort: {
maxKilogramm: -1,
},
},
{
$project: {
maxKilogramm: 0
}
}
Playground
I need some help with Mongo, Mongoose and Node.js.
In the code below, I'd like to join carrinho and produtos collection to retrieve produtos _id, price and description in the same array/object.
My Carrinho Schema
const Carrinho = new mongoose.Schema(
{
title: {
type: String,
},
produtos: [{
price: Number,
produto: { type: mongoose.Schema.Types.ObjectId, ref:
"Produtos" }
}
],
total: {
type: Number,
},
},
{
timestamps: true
})
My Produtos Schema
const Produtos = new mongoose.Schema(
{
description: {
type: String,
required: true,
},
gtin: {
type: String,
required: true,
unique: true,
},
thumbnail: {
type: String,
},
price: {
type: Number,
}
},
{
timestamps: true
}
)
After reading aggregate documentation this is the best I've got:
Carrinho.aggregate([
{ "$match": { "_id": mongoose.Types.ObjectId(req.params.id) } },
{
"$lookup": {
"from": "produtos",
"localField": "produtos._id",
"foreignField": "_id",
"as": "produtosnocarrinho"
}
},
{
"$addFields": {
"total": {
"$reduce": {
"input": "$produtos",
"initialValue": 0,
"in": { "$add": ["$$value", "$$this.price"] }
}
}
}
}
]).exec((err, data) => {
if (err) res.json(err)
res.json(data)
});
And this is the result:
[
{
"_id": "5cb76d7d99c3f4062f512537",
"title": "Carrinho do Lucas",
"produtos": [
{
"_id": "5cafead2bc648978100d7698",
"price": 20.1
},
{
"_id": "5cae911adf75ac4d3ca4bcb6",
"price": 20.1
},
{
"_id": "5cb0f0adc5fb29105d271499",
"price": 20.1
}
],
"createdAt": "2019-04-17T18:16:29.833Z",
"updatedAt": "2019-04-19T00:50:43.316Z",
"__v": 3,
"produtosnocarrinho": [
{
"_id": "5cae911adf75ac4d3ca4bcb6",
"description": "AÇÚCAR REFINADO UNIÃO 1KGS",
"gtin": "7891910000197",
"thumbnail": "7891910000197",
"createdAt": "2019-04-11T00:58:02.296Z",
"updatedAt": "2019-04-11T00:58:02.296Z",
"__v": 0
},
{
"_id": "5cafead2bc648978100d7698",
"description": "HASBRO MR. POTATO HEAD MALETA DE PEÇAS",
"gtin": "5010994598815",
"thumbnail": "pecas_300x300-PU3435f_1.jpg",
"createdAt": "2019-04-12T01:33:06.628Z",
"updatedAt": "2019-04-12T01:33:06.628Z",
"__v": 0
},
{
"_id": "5cb0f0adc5fb29105d271499",
"description": "REPELENTE EXPOSIS INFANTIL SPRAY",
"gtin": "7898392800055",
"thumbnail": "PU28bb9_1.jpg",
"createdAt": "2019-04-12T20:10:21.363Z",
"updatedAt": "2019-04-12T20:10:21.363Z",
"__v": 0
}
],
"total": 60.300000000000004
}
]
The following Query will be help:
models.Carrinho.aggregate(
[
{ "$match": { "_id": mongoose.Types.ObjectId(req.params.id) } },
{
"$lookup": {
"from": "produtos",
"localField": "produtos._id",
"foreignField": "_id",
"as": "produtosnocarrinho"
}
},
{
"$addFields": {
"total": {
"$reduce": {
"input": "$produtos",
"initialValue": 0,
"in": { "$add": ["$$value", "$$this.price"] }
}
}
}
},
{$unwind : '$produtos'},
{$unwind : '$produtosnocarrinho'},
{$redact: { $cond: [{
$eq: [
"$produtos._id",
"$produtosnocarrinho._id"
]
},
"$$KEEP",
"$$PRUNE"
]
}
},
{ $project: {
_id : 1,
title : 1,
produtosData : {
_id : "$produtos._id",
price : "$produtos.price",
description : "$produtosnocarrinho.description"
},
total : 1,
createdAt: 1,
updatedAt : 1
}
},
{
$group : {
_id : {
_id : '$_id',
title : '$title',
total : '$total',
createdAt : '$createdAt',
updatedAt : '$updatedAt'
},
produtosData: {$push: "$produtosData" }
}
},
{ $project: {
_id : '$_id._id',
title : '$_id.title',
total : '$_id.total',
createdAt : '$_id.createdAt',
updatedAt : '$_id.updatedAt',
produtosData: '$produtosData'
}
}
]).exec((err, data) => {
if (err) res.json(err)
res.json(data)
});
Output :
[{
"_id": "5cbc42c24502a7318952d7b2",
"title": "Carrinho do Lucas",
"total": 60.300000000000004,
"createdAt": "2019-04-21T10:15:30.629Z",
"updatedAt": "2019-04-21T10:15:30.629Z",
"produtosData": [{
"_id": "5cafead2bc648978100d7698",
"price": 20.1,
"description": "HASBRO MR. POTATO HEAD MALETA DE PEÇAS"
}, {
"_id": "5cae911adf75ac4d3ca4bcb6",
"price": 20.1,
"description": "AÇÚCAR REFINADO UNIÃO 1KGS"
}, {
"_id": "5cb0f0adc5fb29105d271499",
"price": 20.1,
"description": "REPELENTE EXPOSIS INFANTIL SPRAY"
}]
}]
performance depends on produtos matching data from Lookup Query As we are doing double Unwind.
obj= {
"element-id": 0,
"measurement": [{
"from": "2018-10-17T13:40:00Z",
"to": "2018-10-17T13:45:00Z",
"value": [{
"value": 9,
"label": "fw"
}, {
"value": 7,
"label": "bw"
}]
}, {
"from": "2018-10-17T13:45:00Z",
"to": "2018-10-17T13:50:00Z",
"value": [{
"value": 6,
"label": "fw"
}, {
"value": 8,
"label": "bw"
}]
}]
};
var res = foo(obj);
-- Expected res output:
[ { address: 0,
datetime: 2018-10-17T13:45:00.000Z, <- this is a javascript Date object
day: '2018-10-17',
In: 9,
Out: 7 },
{ address: 0,
datetime: 2018-10-17T13:50:00.000Z, <- this is a javascript Date object
day: '2018-10-17',
In: 6,
Out: 8 }]
Function foo should transform object obj into another object. The resulting res object should be an array whose elements are all structured the same way, and all of them should contain a Date object. How can I test this?
This is what I understood from your post and comment. Navigate me through it if there are any mistakes.
obj= {
"element-id": 0,
"measurement": [{
"from": "2018-10-17T13:40:00Z",
"to": "2018-10-17T13:45:00Z",
"value": [{
"value": 9,
"label": "fw"
}, {
"value": 7,
"label": "bw"
}]
}, {
"from": "2018-10-17T13:45:00Z",
"to": "2018-10-17T13:50:00Z",
"value": [{
"value": 6,
"label": "fw"
}, {
"value": 8,
"label": "bw"
}]
}]
};
let arr = [obj]
let foo = []
arr[0].measurement.map(data => {
let d = new Date()
foo.push({
address: 0,
datetime: d.toISOString(),
day: d.toISOString().slice(0,10),
in: data.value.filter(v => v.label == "fw")[0].value,
out: data.value.filter(v => v.label == "bw")[0].value
})
})
console.log(foo)
My requirement is for a particular user get all the expenses which are grouped based on the month and return the Month and the total expenses for that month.
I have collection something like below.
expenses = {{
"_id": {
"$oid": "5bc0f74df46dae0bf4ffdc39"
},
"user": {
"$oid": "5bab847a5b0d2e2ce8b4cbe5"
},
"date": "15-Mar-2018",
"expenseInfo": "Clothes",
"category": "Shopping",
"amount": 100,
"__v": 0
},
{
"_id": {
"$oid": "5bc0f78bf46dae0bf4ffdc3b"
},
"user": {
"$oid": "5bab847a5b0d2e2ce8b4cbe5"
},
"date": "11-Apr-2018",
"expenseInfo": "mobile",
"category": "Bills",
"amount": 100,
"__v": 0
},
{
"_id": {
"$oid": "5bc0f76cf46dae0bf4ffdc3a"
},
"user": {
"$oid": "5bab847a5b0d2e2ce8b4cbe5"
},
"date": "18-Apr-2018",
"expenseInfo": "Petrol",
"category": "Fuel",
"amount": 20,
"__v": 0
}
}
Here is my Expense schema.
Also, Note that user object(user is a different schema which is referred in Expense schema)
const ExpenseSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
},
date: {
type: String
},
expenseInfo: {
type: String,
required: true
},
category: {
type: String,
required: true
},
amount: {
type: Number,
required: true
}
});
I tried something like this, but I am not getting any data. What is the issue here?
Expense.aggregate([{
$match: {
"_id": request.user.id
}
},
{
"$group": {
"_id": {
"$arrayElemAt": [{
"$split": ["$date", "-"]
}, 1]
},
"Total": {
"$sum": "$amount"
}
}
}
])
I have a model that looks like:
fname: String,
lname: String,
rating: [{
rating: {
type: Number,
enum: RATING,
default: 5
},
date: {
type: Date,
default: Date.now
}
}]
I need to perform updates on this Model by adding new object inside the rating array, with new ratings and dates. I would like to use the bulkwrite method on Model.collection to do this because I need to enable bulk updates so that I don't have to update them one by one.
I created an array bulkUpdateOperations = [] and did the following in a loop:
bulkUpdateOperations.push({
'updateOne': {
'filter': {'_id': item.id},
'update': {$push: {rating: {'rating': item.rating, 'date': Date.now}}}
}
});
Person.collection.bulkWrite(bulkUpdateOperations, {orderd: true, w: 1}, callbackfunc);
But nothing gets updated. I get the following response:
...
...
...
insertedCount: 0,
matchedCount: 0,
modifiedCount: 0,
deletedCount: 0,
upsertedCount: 0,
upsertedIds: {},
insertedIds: {},
n: 0 }
I would be very thankful if someone helped me through this problem.
EDIT
Here is the array I'm sending as POST body to update the records:
[{
"id": "5b7d4d348151700014d25bdd",
"rating": 1
},{
"id": "5b771d10c1e03e1e78b854c2",
"rating": 1
},{
"id": "5b771d7ac1e03e1e78b854c8",
"rating": 1
},{
"id": "5b7bd75a33f88c1af8585be0",
"rating": 1
},{
"id": "5b814a2322236100142ac9f6",
"rating": 1
}]
And here is a sample collection in the DB
{
"_id": {
"$oid": "5b7d4d348151700014d25bdd"
},
"status": "ACTIVE",
"fname": "mr. client",
"lname": "good client",
"contact_info": {
"_id": {
"$oid": "5b7d4d348151700014d25bde"
},
"mobile_no": "0011223344",
"phone_no": "11223344"
},
"handlers": [
{
"_id": {
"$oid": "5b7d4d348151700014d25bdf"
},
"date": {
"$date": "2018-08-22T11:47:00.544Z"
},
"id": {
"$oid": "5b7d45fbfb6fc007d8bdc1f4"
}
}
],
"onboarding_date": {
"$date": "2018-08-22T11:47:00.551Z"
},
"rating": [
{
"rating": 5,
"_id": {
"$oid": "5b814a8e22236100142ac9fc"
},
"date": {
"$date": "2018-08-25T12:22:59.584Z"
}
},
{
"rating": 3,
"_id": {
"$oid": "5b814a8e22236100142ac9fb"
},
"date": {
"$date": "2018-08-25T12:24:46.368Z"
}
}
],
"__v": 0
}
EDIT
Adding upsert: true as a filter for updateOne creates a new document with only rating as its value.
SOLUTION
replace
'filter': {'_id': item.id},
by
'filter': {'_id': mongoose.Types.ObjectId(item.id)},
changing
bulkUpdateOperations.push({
'updateOne': {
'filter': {'_id': item.id},
'update': {$push: {rating: {'rating': item.rating, 'date': Date.now}}}
}
});
to
bulkUpdateOperations.push({
'updateOne': {
'filter': {'_id': mongoose.Types.ObjectId(item.id)},
'update': {$push: {rating: {'rating': item.rating, 'date': Date.now}}}
}
});
worked. Notice the type cast I had to manually perform in
'filter': {'_id': mongoose.Types.ObjectId(item.id)},
I thought mongoose would automatically cast the string to an ObjectId type, but maybe because I'm dropping down a level of abstraction by using Person.collection, mongoose did not auto-cast the itemId.
Please feel free to update this answer if anyone can confirm why I had to cast the string manually.