SyntaxError in `$and` query - mongodb

I am trying to dynamically create an $and query in mongodb. But I get error SyntaxError: missing ; before statement #(shell). Is it not possible to create an $and query dynamically?
db.firstcoll.find({
$and: [{
Thing: {
$in: stuff
}
},
{
Thing: {
$ne: "One three"
}
},
{
Category: "Second"
}
]
}).forEach(function(doc1) {
var words = doc1.Thing.split(' ');
var NewQuery;
if (words.length == 1) {
NewQuery = {
$and: [{
Thing: {
$regex: words[0]
}
},
{
Category: doc1.Category
}
]
}
};
if (words.length == 2) {
NewQuery = {
$and: [{
Thing: {
$regex: words[0]
}
}, {
Thing: {
$regex: words[1]
}
}, {
Category: doc1.Category
}]
}
};
db.secondcoll.find(
NewQuery
).forEach(function(doc2) {
print("stuff: ", doc2.stuff)
})
})

Related

How to remove substring of value of a specific field in mongodb?

I have the following mongo document:
{ Name: Peter,
Email: peter#mail.com,
EmailSuffix: peter#mail.com
}
I want to remove the substring before "#" of "EmailSuffix" field in all documents of the collection, so that the result will be:
{ Name: Peter,
Email: peter#mail.com,
EmailSuffix: #mail.com
}
I have tried the following:
db.collection.aggregate( [
{
$match: { EmailSuffix: { $regex: /.+?(?=#)/ } }
},
{
$addFields: {
EmailSuffix: { $split: [ "$EmailSuffix", "?" ] }
}
}
] ).forEach( doc => db.collection.updateMany( { _id: doc._id }, { $set: { EmailSuffix: doc.EmailSuffix[0] } } )`
But it doesn't run.
Use $indexOfCP to locate the first #. Then use $substrCP to do usual substring extraction.
db.collection.update({},
[
{
"$addFields": {
"EmailSuffix": {
"$substrCP": [
"$EmailSuffix",
{
"$indexOfCP": [
"$EmailSuffix",
"#"
]
},
{
"$strLenCP": "$EmailSuffix"
}
]
}
}
}
],
{
multi: true
})
Mongo Playground

Mongodb project inside array of object with array of object

MongoDB
I have data like:-
[
{
review: [
{
title: "Title1",
professor: [
{
id: "1",
accept: false
},
{
id: "2",
accept: false
}
]
}
]
},
{
review: [
{
title: "Title2",
professor: [
{
id: "3",
accept: false
},
{
id: "2",
accept: false
}
]
}
]
}
]
I want title and professor array with filter of specific id (like "1")
My code:-
for match i use below code and it works perfectly fine
$match
{
review: {
$elemMatch: {
professor: {
$elemMatch: {
id: "1"
}
}
}
}
}
for project i use below code
$project
{
review: {
title:1,
professor:{
$filter:{
input: "$review.professor", (I try only professor but give null)
as: "professor",
cond: {$eq:["$$professor.id", "1" ]}
}
}
}
}
Problem is that professor show array but comes with empty data
Playground
Unwind stage could help you.
db.collection.aggregate([
{
"$match": {
review: {
$elemMatch: {
professor: {
$elemMatch: {
id: "1"
}
}
}
}
}
},
{
"$unwind": "$review"
},
{
$project: {
review: {
title: 1,
professor: {
$filter: {
input: "$review.professor",
as: "professor",
cond: {
$eq: [
"$$professor.id",
"1"
]
}
}
}
}
}
}
])

mongodb $pull in array with another array

Help me please to remove elements in an array with such document schema:
contracts: [
{
bandwidth: {
calculated: {
value: Number,
documents: [id1, id2, id3, id4],
}
}
}
]
I want to delete elements in all documents array that are in filter array.
I tried:
const documentsToDelete = [id2, id3]
const points = await Point.updateMany({
$pull: {
contracts: {"bandwidth.calculated.documents": {$in: documentsToDelete}}
},
});
But it does not work. The resulting array must contain "id1" and "id4"
Correct the things,
the first parameter is the query part to match the condition
the contracts is an array so use $[] to update operation in all elements
const documentsToDelete = [id2, id3];
const points = await Point.updateMany(
{},
{
$pull: {
"contracts.$[].bandwidth.calculated.documents": {
$in: documentsToDelete
}
}
}
)
Playground
bellow quires worked for me well
let feed = await Feed.findOneAndUpdate(
{
_id: req.params.id,
feeds: {
$elemMatch: {
type: FeedType.Post,
locations: {
$elemMatch: {
uniqueName,
},
},
},
},
},
{
$pull: {
//#ts-ignore
'feeds.$[].locations': { uniqueName },
},
},
{ new: true }
);
or
let feed = await Feed.findOneAndUpdate(
{
$and: [
{
_id: req.params.id,
},
{
'feeds.$[].locations': {
$elemMatch: {
uniqueName,
},
},
},
],
},
{
$pull: {
//#ts-ignore
'feeds.$[].locations': { uniqueName },
},
},
{ new: true }
);

Retrieve data inside nested array in MongoDB and paginate aggregation show all docs

If there are following documents inside a collection:
{
"_id": "8048d05478813e439442abac",
"projectName": "Y-10000-A",
"archived": false,
"tabs":
[
{
"visible": true,
"permisos": ["604892e9266fc72b04be62f0", "12312131b04be62f0"]
},
{
"visible": true,
"permisos": ["12312131b04be62f0"]
}
],
},
{
"_id": "9048d05478813e439442abad",
"projectName": "Y-10000-B",
"archived": false,
"tabs": [{
"visible": true,
"permisos": ["12312131b04be62f0"]
}]
},
{
"_id": "9048d05478813e439442abae",
"projectName": "Y-10000-C",
"archived": true,
"tabs": [{
"visible": true,
"permisos": ["604892e9266fc72b04be62f0"]
}]
},
I want to filter all the projects that have at least one tab matching the user._id in the permisos array. Also I am filtering by archived and by text. The text search isn't working properly.
const projectsAggregation = await projectSchema.aggregate([
{ $match: { $text: { $search: "Y" } } },
{ $match : { archived: false} },
{
$addFields: {
tabs: {
$filter: {
input: "$tabs",
as: "tab",
cond: { $in: [user._id, "$$tab.permisos"] }
}
}
}
},
{
$match: {
$expr: {
$gt: [{ $size: "$tabs" }, 0]
}
}
}
const projectsDocs = await projectSchema.aggregatePaginate(projectsAggregation, {
limit: pagination.limit ? parseInt(pagination.limit) : 10,
page: pagination.page ? parseInt(pagination.page) + 1 : 1
});
I want to paginate the aggregation. I am using mongoose-aggregate-paginate-v2. It returns all the documents of the schema. It should return only the documents from projectsAggregation. Also the
{ $match: { $text: { $search: "Y" } } }, it doesn't work.
Raw query:
let user_id = "604892e9266fc72b04be62f0";
let regex = /^Y/
db.projects.aggregate([
{
$match: {
archived: false,
projectName: {
$regex: regex,
$options: 'i'
}
}
},
{
$addFields: {
tabs: {
$filter: {
input: "$tabs",
as: "tab",
cond: { $in: [user_id, "$$tab.permisos"] }
}
}
}
},
{
$match: {
$expr: {
$gt: [{ $size: "$tabs" }, 0]
}
}
}
]);
Using Mongoose:
File: project_schema.js
const mongoose = require('mongoose');
const mongoosePaginate = require('mongoose-aggregate-paginate-v2');
let projectSchema = new Schema({
// Put your schema here
},
{
collection: 'projects'
});
projectSchema.plugin(mongoosePaginate); // <- This step is important!
module.exports = mongoose.model('projects', projectSchema);
File: project_manager.js
let user_id = "604892e9266fc72b04be62f0";
let regex = /^Y/
const projectAggQuery = projectSchema.aggregate([
{
$match: {
archived: false,
projectName: {
$regex: regex,
$options: 'i'
}
}
},
{
$addFields: {
tabs: {
$filter: {
input: "$tabs",
as: "tab",
cond: { $in: [user_id, "$$tab.permisos"] }
}
}
}
},
{
$match: {
$expr: {
$gt: [{ $size: "$tabs" }, 0]
}
}
}
]);
const projectsDocs = await projectSchema.aggregatePaginate(projectAggQuery, {
limit: pagination.limit ? parseInt(pagination.limit) : 10,
page: pagination.page ? parseInt(pagination.page) + 1 : 1
});

How to Combine GeoQuery with another separate query in MongoDB and paginate result?

let params = {
$or: [
{//STATUS1 PERSON
status: { '$in': ['Status1'] }, object: { '$in': ['Person'] },
geometry: {
$near: {
$maxDistance: 160000,
$geometry: {
type: "Point",
coordinates: [geoCoordinates[1], geoCoordinates[0]]
}
}
},
name: { '$in': req.user.names },
sessionStartTime: { "$gte": new Date() },
$and: [
{
user_id: '',
},
{
userID: { $exists: false }
}
]
},
{ //STATUS1 ALL OTHER ITEM TYPES
status: { '$in': ['Status1'] }, object: { '$in': ['Animal', 'Planet', 'Star'] },
name: { '$in': req.user.names },
sessionStartTime: { "$gte": new Date() },
$and: [
{
user_id: '',
},
{
userID: { $exists: false }
}
]
},
{ //ALL ITEM TYPES WITH STATUS2 AND STATUS3
status: { '$in': ['Status2', 'Status3'] }, object: { '$in': ['Person', 'Animal', 'Planet', 'Star'] },
user_id: req.user._id
}
]
}
var options = {
page: 1,
limit: 5
};
let foundItems = await User.paginate(params, options).then(function (result) {
});
With this query, I'm getting the following error:
MongoError: geoNear must be top-level expr
How do I include geometry query as one query among others and return the combined result with pagination ? Or is there a different way to achieve the same result?