Here is my code
const searchStringResult = (payload.match?.searchString);
const paginate = [
{
$facet: {
metadata: [{ $count: 'total' }],
data: [
{ $skip: payload.paginate?.skip || 0 },
{ $limit: payload.paginate?.limit || 10 },
],
},
},
{
$match: {
searchfields: {$regex: searchStringResult,$options: "-i"}
}
}
];
when I console log these code it doesn't show any error
but in console
[{"$facet":{"metadata":[{"$count":"total"}],"data":[{"$skip":0},{"$limit":10}]}},{"$match":{"searchfields":{"$regex":"a","$options":"-i"}}}]
Related
I currently have a Mongo query that looks like this:
const user = await User.findOne({ userId }).lean() || []
const contributions = await Launch.aggregate([
{ $sort: { addedAt: -1 } },
{ $limit: 10 },
{
$match: {
_id: { $in: user.contributions }
}
},
{
$addFields: {
activity: 'contribution',
launchName: '$name',
launchId: '$_id',
date: '$addedAt',
content: '$description'
}
}
])
But instead of having two different Mongo queries (findOne and aggregate), how can I combine them into one query?
I tried this but it just errors out immediately in the lookup part:
const contributions = await Launch.aggregate([
{ $sort: { addedAt: -1 } },
{ $limit: 10 },
{
$lookup: {
from: 'user',
let: { id: $user.contributions },
pipeline: [
{ $match: { $expr: { $in: [$_id, $$user.contributions] } } }
],
localField: '_id',
foreignField: 'userId',
as: 'user'
}
},
{
$addFields: {
activity: 'contribution',
launchName: '$name',
launchId: '$_id',
date: '$addedAt',
content: '$description'
}
}
])
I've never used the pipeline option so a little confused onn how to fix this problem?
Enclose these $user.contributions, $_id with quotes in order to make the query valid.
Since you declare the id variable with the value of user.contributions. You should use the variable with $$id instead of $$user.contributions.
I don't think the localField and foreignField are needed as you are mapping/joining with pipeline.
Your aggregation query should be looked as below:
const contributions = await Launch.aggregate([
{ $sort: { addedAt: -1 } },
{ $limit: 10 },
{
$lookup: {
from: 'user',
let: { id: "$user.contributions" },
pipeline: [
{ $match: { $expr: { $in: ["$_id", "$$id"] } } }
],
as: 'user'
}
},
{
$addFields: {
activity: 'contribution',
launchName: '$name',
launchId: '$_id',
date: '$addedAt',
content: '$description'
}
}
])
I have Offers table 2 row exit_customs and destination_customs. This 2 row has a my Customs table id. My problem is how to two(exit_customs and destination_customs) foreign key one(Customs) table?
Here is my list query function
router.post('/api/logistic/offers/get-offers', async (req, res) => {
const {limit, page, sortColumn, sortType, search} = req.body;
const total = await Offers.findAll();
const offersList = await Offers.findAll({
limit: limit,
offset: (page - 1) * limit,
order: [
[sortColumn, sortType]
],
where: {
[Op.or]:[
{
offers_no: {
[Op.substring]: [
search
]
}
},
{
agreement_date: {
[Op.substring]: [
search
]
}
},
{
routes: {
[Op.substring]: [
search
]
}
},
{
type_of_the_transport: {
[Op.substring]: [
search
]
}
},
]
}
});
res.json({
total: total.length,
data: offersList
});
})
this solution connects the two data in the first table to the id in the other table as you want. hope it helps
Offers.belongsTo(Customs, {as: 'Exit_customs', foreignKey: 'exit_customs'});
Offers.belongsTo(Customs, {as: 'Destination_customs', foreignKey: 'destination_customs'});
router.post('/api/logistic/offers/get-offers', async (req, res) => {
const {limit, page, sortColumn, sortType, search} = req.body;
const total = await Offers.findAll();
const offersList = await Offers.findAll({
limit: limit,
offset: (page - 1) * limit,
order: [
[sortColumn, sortType]
],
where: {
[Op.or]: [
{
offers_no: {
[Op.substring]: [
search
]
}
},
{
agreement_date: {
[Op.substring]: [
search
]
}
},
{
routes: {
[Op.substring]: [
search
]
}
},
{
type_of_the_transport: {
[Op.substring]: [
search
]
}
},
]
},
include: [{
model: Customs,
as: 'Exit_customs'
}, {
model: Customs,
as: 'Destination_customs'
}]
});
res.json({
total: total.length,
data: offersList
});
})
You can give foreign key using "as" keyword, please add below code in your Offers models file
static associate(models) {
models.Offers.belongsTo(models.Customs, {
foreignKey: "exit_customs",
as: "exitCustomsDetails",
});
models.Offers.belongsTo(models.Customs, {
foreignKey: "destination_customs",
as: "destinationCustomsDetails",
});
}
i'm trying to accomplish the following in mongoose:
Say i have the following collection
{
"_id": {
"$oid": "111"
},
"email": "xxx#mail.com",
"givenName": "xxx",
"familyName": "xxx",
"favoriteProducts": [{
"soldTo": "33040404",
"skus": ["W0541", "W2402"]
}, {
"soldTo": "1223",
"skus": ["12334"]
}]
}
i want to be able to add a sku to the favorite products array based on soldTo and _id.
When doing this there are two possible scenarios.
a. There is already an object in favoriteProducts with the given soldTo in which case the sku is simply added to the array.(for example add sku '12300' to soldTo '1223' for id '111')
b. There is no object with the given soldTo yet in which case this object need to be created with the given sku and soldTo. (for example add sku '123' to soldTo '321' for id '111')
so far i've done this but i feel like there is a way to do it in one query instead.
private async test() {
const soldTo = '1223';
const sku = '12300';
const id = '111';
const hasFavoriteForSoldTo = await userModel.exists({
_id: id,
'favoriteProducts.soldTo': soldTo,
});
if (!hasFavoriteForSoldTo) {
await userModel
.updateOne(
{
_id: id,
},
{ $addToSet: { favoriteProducts: { skus: [sku], soldTo } } },
)
.exec();
} else {
await userModel
.updateOne(
{
_id: id,
'favoriteProducts.soldTo': soldTo,
},
{ $addToSet: { 'favoriteProducts.$.skus': sku } }
)
.exec();
}
}
Use update-documents-with-aggregation-pipeline
Check out mongo play ground below. Not sure you want Output 1 or Output 2.
Output 1
db.collection.update({
_id: { "$oid": "111222333444555666777888" }
},
[
{
$set: {
favoriteProducts: {
$cond: {
if: { $in: [ "1223", "$favoriteProducts.soldTo" ] },
then: {
$map: {
input: "$favoriteProducts",
as: "f",
in: {
$cond: {
if: { $eq: [ "1223", "$$f.soldTo" ] },
then: { $mergeObjects: [ "$$f", { skus: [ "12300" ] } ] },
else: "$$f"
}
}
}
},
else: {
$concatArrays: [ "$favoriteProducts", [ { skus: [ "12300" ], soldTo: "1223" } ] ]
}
}
}
}
}
],
{
multi: true
})
mongoplayground
Output 2
db.collection.update({
_id: { "$oid": "111222333444555666777888" }
},
[
{
$set: {
favoriteProducts: {
$cond: {
if: { $in: [ "1223", "$favoriteProducts.soldTo" ] },
then: {
$map: {
input: "$favoriteProducts",
as: "f",
in: {
$cond: {
if: { $eq: [ "1223", "$$f.soldTo" ] },
then: {
$mergeObjects: [
"$$f",
{ skus: { $concatArrays: [ [ "12300" ], "$$f.skus" ] } }
]
},
else: "$$f"
}
}
}
},
else: {
$concatArrays: [ "$favoriteProducts", [ { skus: [ "12300" ], soldTo: "1223" } ] ]
}
}
}
}
}
],
{
multi: true
})
mongoplayground
I have a document form similar to this
{
"doc-id":2,
"interfaces": [
{
"interface-role": "ON",
"port-nb": 1
},
{
"interface-role": "OFF",
"port-nb": 2
},
{
"interface-role": "ON",
"port-nb": 3
},
{
"interface-role": "OFF",
"port-nb": 3
}
]
}
I want to query and get specific document interfaces and also have the ability to filter ON and OFF and that's what I did try so far
const doc = await this.doc
.findOne({
'doc-id': docId,
'interfaces["interface-role"]': interfaceRole, //ON or OFF
})
.select({ interfaces: 1, _id: 0 })
.exec();
so the result that I want to have is getting interfaces if there's no filter for interfaces-role and if there's one get the interfaces filtered
You can use a $or to do the conditional filtering with a $filter.
db.collection.aggregate([
{
$match: {
"doc-id": 2
}
},
{
"$addFields": {
"interfaces": {
"$filter": {
"input": "$interfaces",
"as": "i",
"cond": {
$or: [
{
$eq: [
null,
<interfaceRole>
]
},
{
$eq: [
"$$i.interface-role",
<interfaceRole>
]
}
]
}
}
}
}
}
])
Here is the Mongo playground when interfaceRole is not supplied.
Here is the Mongo playground when interfaceRole is supplied.
I am struggling to create an aggregate query for my MongoDB database.
here is my input array
recipients = [1,2,7]
here is my database collection
{
"chapter": 1,
"targets": [
{
type: 'user',
recipient: 1
}
]
},
{
"chapter": 1,
"targets": [
{
type: 'user',
recipient: 2
}
]
},
{
"chapter": 2,
"targets": [
{
type: 'user',
recipient: 3
}
]
},
{
"chapter": 3,
"targets": [
{
type: 'user',
recipient: 4
}
]
},
the desired output
should be [] because 7 doesn't exist in targets.recipient in the collection
here is what I've tried so far
db.collection.aggregate([
{
$match: {
'targets.recipient': { $in: recipients },
},
}
])
Any suggestions, thank you.
The way $in works is that it returns the document if there's any match between it's value and the array you're passing as a parameter. It looks like in your case you can use $in for initial filtering but then you want to return the result only if the result set contains all the values from the input array. In order to achieve it you can use $group to get all matching results and then apply $all:
db.collection.aggregate([
{
$match: { "targets.recipient": { $in: [1,2,7] } }
},
{
$group: {
_id: null,
docs: { $push: "$$ROOT" }
}
},
{
$match: { "docs.targets.recipient": { $all: [1,2,7] } }
}
])
Mongo Playground
// only matched documents will be shown.
> db.targets.aggregate([ {$match:{"targets.recipient":{$in:[1,2,7]}}}, {$project:{chapter:1,targets:1}} ]).pretty();
{
"_id" : ObjectId("5f5de14c598d922a1e6eff4d"),
"chapter" : 1,
"targets" : [
{
"type" : "user",
"recipient" : 1
}
]
}
{
"_id" : ObjectId("5f5de14c598d922a1e6eff4e"),
"chapter" : 1,
"targets" : [
{
"type" : "user",
"recipient" : 2
}
]
}
>