This question already has answers here:
How do you use a variable in a regular expression?
(27 answers)
Closed 4 years ago.
how to use search_key variable as field value instead of static value BRO
if(search_key!=''){
dbo.collection("assets").aggregate([
{
"$match": { $and: [ { status: 1 }, { $or: [ { maker_name : /^.*BRO.*$/i }, { serial_number : /^.*BRO.*$/i } ] } ] }
},
{
$lookup:
{
from: 'asset_type',
localField: 'asset_type',
foreignField: 'asset_type_id',
as: 'asset_type_details'
}
}
]).sort({_id:-1}).toArray(function(err, result) {
if (err) throw err;
res.status(200).json({'return_data': result });
db.close();
});
}
Try this way
{ serial_number: { $regex: `${search_key}.*`, $options: 'i' } }
Use this same thing for maker_name also.
This is works for me.
We need to pass a string to the function. so we can simply change that by passing query string.
if(search_key!=''){
let query_string = "/^.*" + search_key + ".*$/i" // we are creating the query string here
dbo.collection("assets").aggregate([
{
"$match": { $and: [ { status: 1 }, { $or: [ { maker_name : query_string }, { serial_number : query_string } ] } ] }
},
{
$lookup:
{
from: 'asset_type',
localField: 'asset_type',
foreignField: 'asset_type_id',
as: 'asset_type_details'
}
}
]).sort({_id:-1}).toArray(function(err, result) {
if (err) throw err;
res.status(200).json({'return_data': result });
db.close();
});
}
try like this :
if(search_key!=''){
dbo.collection("assets").aggregate([
{
"$match": { $and: [ { status: 1 },
{ $or: [
{ maker_name : '/^.*'+ search_key +'*$/i' },
{ serial_number : '/^.*'+ search_key +'*$/i' }
]
}
]
}
},
{
$lookup:
{
from: 'asset_type',
localField: 'asset_type',
foreignField: 'asset_type_id',
as: 'asset_type_details'
}
}
]).sort({_id:-1}).toArray(function(err, result) {
if (err) throw err;
res.status(200).json({'return_data': result });
db.close();
});
}
Related
in the shopping cart project, am trying to get the total amount in the cart but my aggregation method has some problems , how to fix this ?
error
callback(new error_1.MongoServerError(document));
^
MongoServerError: PlanExecutor error during aggregation :: caused by :: Failed to parse number '1,39,999' in $convert with no onError value: Did not consume whole string.
user_helpers.js this the aggregation
getTotalAmount:(userId)=>{
return new Promise(async(resolve,reject)=>{
let total=await db.get().collection(collection.CART_COLLECTION).aggregate([
{
$match:{user:objectId(userId)}
},
{
$unwind:'$products'
},{
$project:{
item:'$products.item',
quantity:'$products.quantity',
}
},
{
$lookup:{
from:collection.PRODUCT_COLLECTION,
localField:'item',
foreignField:'_id',
as:'product'
}
},
{
$project:{
item:1,quantity:1,product:{$arrayElemAt:['$product',0]}
}
},
{
$group:{
_id:null,
total:{$sum:{$multiply:[{ $toInt: '$quantity'},{ $toInt: '$product.Price' }]}} // my assumption , here comes the error
}
}
]).toArray()
resolve(total.length > 0 ? total[0].total: 0) // or here
})
}
user.js
// GET: view shopping cart contents
router.get('/cart',middleware.verifyLogin,async(req,res,next)=>{
try{
let user=req.session.user._id;
let products =await userHelpers.getCartProducts(req.session.user._id)
let totalValue=0
if(products.length>0){
totalValue=await userHelpers.getTotalAmount(req.session.user._id)
let proId=req.params.id
console.log('proId>>>>>>>>>>',proId);
}
console.log('products>',products)
console.log("user...",user);
res.render('user/cart',{products,user,totalValue,});
}catch (error) {
console.log(error);
}
})
It comes when you click the cart button error is getting ,
how to fix this ?
The error message says itself, your database contains strings like 1,39,999. When MongoDB tries to convert these to an integer, it fails because of the commas. So, before converting the string to an integer, you should remove all the commas and other non-numeric characters from the string. Like this:
db.collection.aggregate([
{
$match: {
user: ObjectId("userId433456666666666666")
}
},
{
$unwind: "$products"
},
{
$project: {
item: "$products.item",
quantity: "$products.quantity",
}
},
{
$lookup: {
from: "collection.PRODUCT_COLLECTION",
localField: "item",
foreignField: "_id",
as: "product"
}
},
{
$project: {
item: 1,
quantity: 1,
product: {
$arrayElemAt: [
"$product",
0
]
}
}
},
{
$group: {
_id: null,
total: {
$sum: {
$multiply: [
{
$toInt: '$quantity'
},
{
$toInt: {
"$replaceAll": {
"input": "$product.Price",
"find": ",",
"replacement": ""
}
}
}
]
}
}
}
}
]).toArray()
Here we are using $replaceAll to replace the commas with an empty string.
I have a mongoDB database set up with a express server.
I try to access a object which is inside an array in a document.
I have this route :
app.get("/api/" + BLOGS_COLLECTION + "/:blogId" + "/post" + "/:postId", function (req, res) {
db.collection(BLOGS_COLLECTION).aggregate([
{ $match: { _id: req.params.postId } }, {
$project: {
posts: {
$filter: {
input: "$posts",
as: "posts",
cond: { $eq: ["$$posts._id", req.params.postId] }
}
}
}
}].toArray((err, doc) => {
console.log(doc)
if (err) {
handleError(res, err.message, "Failed to get post");
} else {
res.status(200).send(doc);
}
}));
});
But it returns an error :
[{(intermediate value)},{(intermediate value)}].toArray is not a function
If I do not use the toArray but a plain function, it can't construct to json to send it to the front.
I do not use Mongoose.
If the code above can't work, how can I query only the object I want inside the array ?
P.S: this is how my database is made :
_id:60336bcc961785586471938b
title:"<p>ttttttttttttttttttttttttttt</p>"
description:"<p>tttttttttttttttttttttttttt</p>"
authorId:"60336bb5961785586471938a"
createDate:2021-02-22T08:31:08.889+00:00
posts:
0:
_id:"53394732-d60b-c869-1fed-1fb82c03780f"
title:"<p>iiiiiiiiiiiiiiiiiiiiiiiiiiiii</p>"
content:"<p>iiiiiiiiiiiiiiiiiiii</p>"
date:"2021-02-22T08:31:14.911Z"
You need to call toArray on the cursor reference you get back from the aggregation and not on the aggregation array:
db.collection(BLOGS_COLLECTION).aggregate([
{ $match: { _id: req.params.postId } },
{
$project: {
posts: {
$filter: {
input: "$posts",
as: "posts",
cond: { $eq: ["$$posts._id", req.params.postId] }
}
}
}
}
],
(err, cursor) => {
if (err) {
handleError(res, err.message, "Failed to get post");
} else {
cursor.toArray((error, documents) => {
if (error) { return handleError(res, error.message, "Failed to get post"); }
console.log(documents)
res.status(200).send(documents);
});
}
});
MongoDB Aggregation Pipeline
Your stages between square prackets should look like this:
[
{ $match: { _id: ObjectId( req.params.blogId) } },
{
$project: {
posts: {
$filter: {
input: "$posts",
as: "posts",
cond: { $eq: ["$$posts._id", ObjectId(req.params.postId)] }
}
}
}
},
{$unwind : "$posts" },
{$replaceRoot :{ newRoot:"$posts"}
]
After filtering and projecting, unwind array objects and then simply replace the root. And of course, follow the instructions from the previous answer about the usage of toArray on aggregate cursor result.
I am trying to using aggregate function for fetching data from two documents. I am able to do it but i am finding a solution how can i apply $project in lookup table only
below is my approach
app.get('/getAllDetailById',(req,res)=>{
if(db){
// lookup
db.collection("points").aggregate(
[
{ "$addFields": { "enquiry_by": { "$toObjectId": "$enquiry_by" }}},
{
"$lookup" : {
from: "user",
localField: "enquiry_by",
foreignField: "_id",
as: "userDetails"
}
},
{ $unwind: "$userDetails"},
]
).toArray()
.then(result=>{
console.log(result[0])
}).catch(err=>{
res.send(err)
})
}
})
What i want is get all fields from points table and from user table i just want name and username. I have used $project but than its return only fields defined in this.
{ $project: {"userDetails.name":1, "userDetails.username":1,"_id":0} }
Is there any way that $project can be applied separately for user table
You can use pipeline in the lookup if you are using mongodb >= 3.6: https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/#join-conditions-and-uncorrelated-sub-queries
So your code will look like:
app.get('/getAllDetailById',(req,res)=>{
if(db){
// lookup
db.collection("points").aggregate(
[
{ "$addFields": { "enquiry_by": { "$toObjectId": "$enquiry_by" }}},
{
"$lookup" : {
from: "user",
let: { "enquiry_by": "$enquiry_by" },
pipeline: [
{
"$match": {
"$expr": {
"$eq": ["$_id", "$$enquiry_by"]
}
},
"$project": {
"$name": 1,
"$username": 1,
}
},
],
as: "userDetails"
}
},
{ $unwind: "$userDetails"},
]
).toArray()
.then(result=>{
console.log(result[0])
}).catch(err=>{
res.send(err)
})
}
})
Consider the query in Mongoose :
let StudentCodes = .... // getting this from somewhere
await Students.aggregate(
[
{
$project: {
StudentCODE: "$StudentCODE",
StudName: "$StudName",
StudProfileDesc: "$StudProfileDesc",
IsReviewed: {
$cond: [{ $eq: [StudentCodes, "$StudentCODE"] }, 1, 0]
}
}
}
],
function(err, results) {
if (err) {
console.log(err);
}
console.log(results);
return res.status(200).json(results);
}
);
How can We project IsReviewed as true or false if the property StudentCODE exists in the array StudentCodes ?
Try as below, you can use $in in $cond to do that :
let StudentCodes = .... // getting this from somewhere
await Students.aggregate(
[
{
$project: {
StudentCODE: "$StudentCODE",
StudName: "$StudName",
StudProfileDesc: "$StudProfileDesc",
IsReviewed: {
$cond: [{ $in: ["$StudentCODE", StudentCodes] }, true, false]
}
}
}
],
function (err, results) {
if (err) {
console.log(err);
}
console.log(results);
return res.status(200).json(results);
}
);
I am using aggregation to fetch the value from two collection, One is folder and another is inspections. I am getting all the data's but am getting Inspection count is 0
My code :
mongo.folder.aggregate([
{
$lookup:
{
from: 'inspections',
localField: '_id',
foreignField: 'projectID',
as: 'projectdata'
}
},
{ $match : {
$and: [
querydata
]
}
},
{
"$project": {
"folder_name" : "$folder_name",
"location_name": "$location_name",
"architect_name" :"$architect_name",
"cover_img": "$cover_img",
"created_date" : "$created_date",
"parent_id":"$parent_id",
"share" : "$share",
"share_id":'$share_id',
"user_id": "$user_id",
"customer_id" : "$customer_id",
"download_access" : "$download_access",
"inspection_count": {
"$size": {
"$filter": {
"input": "$projectdata.inspection_data",
"as": "el",
"cond": { "$eq": [ "$$el.published", "Y" ] }
}
}
}
}
}
]).exec(function (err, response) {
console.log("Inside Parent Id 1")
console.log(response)
if(response){
response.splice(0, 0, responseparent);
}
else
{
response = responseparent;
}
if (err){
res.json({ 'folder': [], 'filelist': [] }); } else {
res.json({ 'folder': response, 'filelist': [] }); }
});
Here inspection Count should be 3 But am getting Zero count. How Do i find the size of the array based upon their field value .
I have used filter even though its showing 0 in count