Im using mongoose with a MongoDb. The test runs are saved with the current state they are in. I would like to get the open or running test runs and the last ten finished test runs.
How can this be achieved?
The query i have for now looks like this:
...
models.testRun.find()
.or([
{ isOpen: true },
{ isRunning: true },
{ $and: [{ isOpen: false }] } // missing statement to select 10 entries
])
.sort({
updatedAt: "descending"
})
.populate(populateQuery)
.exec((error, testRuns) => {
console.log(testRuns);
});
At the last $or entry i thought i can enter a $and query which selects the last ten test runs.
The schema of a test run looks like this
const testRunSchema = mongoose.Schema({
isOpen: {
type: Boolean,
required: true,
},
isRunning: {
type: Boolean,
required: true,
},
hasError: {
type: Boolean,
required: true,
},
}, { timestamps: true });
...
models.testRun.find()
.or([
{ isOpen: true },
{ isRunning: true },
{ $and: [{ isOpen: false }] } // missing statement to select 10 entries
])
.sort({
updatedAt: "descending"
}
.{ $limit : 10 })
.populate(populateQuery)
.exec((error, testRuns) => {
console.log(testRuns);
});
The above addition should work, unless something specific about Mongoose
Related
I have collection like this.
const Device: Schema = new Schema(
{
location: {
type: String,
required: true,
},
macAddress: {
type: String,
required: true,
immutable: true,
},
ip: {
type: String,
required: true,
immutable: true,
},
},
{
timestamps: true,
versionKey: false,
collection: 'Device',
}
);
I want to update immutable fields with my endpoints and i use this function and doesnt work.
Device.findOneAndUpdate(
{ _id: req.params.mdeviceId },
{ $set: { macAddress: req.body.macAddress, ip: req.body.ip},
{ new: true, upsert: true }
);
How can i update this specific fields?
I would guess req.params.mdeviceId is a string and needs to be casted to ObjectId, this is not related to the immutable property as you are providing the new flag which allows to bypass the schema protection, try using this:
Device.findOneAndUpdate(
{ _id: new mongoose.Types.ObjectId(req.params.mdeviceId) },
{ $set: { macAddress: req.body.macAddress, ip: req.body.id},
{ new: true, upsert: true }
);
I have the following schema (NestJS + Mongoose):
#Schema({ timestamps: true })
export class Listing {
#Prop({
type: [{
bidderId: { type: Types.ObjectId, required: true, select: false, ref: User.name, index: true },
amount: { type: Number, required: true },
date: { type: Date, required: true }
}],
select: false
})
bids!: Bid[]
}
so basically every listing document has an array of bids.
now I notice that automatically mongoDB (or mongoose) creates _id field for every bid item I put into the bids array.
My question is, If I have a bid's _id, how can I query it's item from the listing's bids array? something like:
// Adding a new bid to the listing, and retrieving the updated listing
const listingWithAddedBid = await this.listingModel.findByIdAndUpdate(listingId, {
$push: {
bids: {
$each: [{
amount: bidInfo.amount,
bidderId: new Types.ObjectId(user.id),
date: new Date()
}],
$sort: { amount: -1 }
}
}
}, { new: true })
// Getting the new bid's _id from the array (it will be at index 0 because we sort buy amount)
const newBidId = listingWithAddedBid.bids[0]._id
// here how can I query the entire bid item from the array with 'newBidId'? this won't work
this.listingModel.findById(newBidId) // returns null
https://docs.mongodb.com/manual/tutorial/query-array-of-documents/
https://docs.mongodb.com/manual/indexes/#default-_id-index
this.listingModel.findOne({ "bids._id": newBidId, {}, {}, (error, doc) =>
{
if (error) {
....
}
if (doc) {
....
} else {
...//'Not Found';
}
});
I have the following mongoose schema:
export class Auction {
... Some other fields ...
#Prop({ type: mongoose.Schema.Types.ObjectId, ref: User.name, required: true, index: true })
seller!: string | User | Types.ObjectId
#Prop({
type: [{
bidderId: { type: Types.ObjectId, required: true, select: false },
amount: { type: Number, required: true },
date: { type: Date, required: true }
}],
select: false
})
bids?: Bid[]
}
I need an endpoint method that returns the bids of an Auction, but with the following rule:
include bids.bidderId if the user who's requesting the bids is the seller of the auction, else exclude bids.bidderId from the projection.
How can I implement that? assuming I have this method:
async getBidsOfAuction(auctionId: string, user: UserDocument) {
// In case user.id === auction.seller, return all the fields including bids.bidderId
return await this.auctionModel.findOne({_id: auctionId, seller: user.id}).select('+bids +bids.bidderId')
// else, exclude bids.bidderId
return await this.auctionModel.findById(auctionId).select('+bids')
}
I just can't know if auction.seller === user.id before I query the auction, and I don't want to manually (in JS) remove bids.bidderId from the bids array after the query because its seems redundant.
Is there a way to conditionally query If the auction's seller equals to the user id, include bids.bidderId, else exclude?
async getBidsOfAuction(auctionId: string, user: UserDocument) {
user.aggregate().match({_id: auctionId})
.project({
'seller': 1,
'type': 1,
'bids': {
$cond: {
if: {
'$eq': ['$seller', user.id]
},
then: '$bids.bidderId',
else: null
}
},
})
.exec(callback);
}
I have a NodeJS application where I use the mongoose library to communicate with my mongo database.
The application is about a game, where multiple rounds are played. And after each round, the results of the round are submitted! I want the values (a json) to be push to players.rounds. I have an _id and a players.id to determine where to push.
This is what I thought would be the right way (and I'm still a newbie in mongoose). It prints me no error, but the db document is not affected. Still zero items in players.rounds.
This is what I thought would be the right way (and I'm still a newbie in mongoose).
My mongoose schema:
const gameSchema = new mongoose.Schema(
{
categories: [
{ type: String }
],
countdown: Number,
players: [{
_id: false,
id: String,
rounds: [
{ type: Map, of: String }
],
score: { type: Number, default: 0 },
ready: { type: Boolean, default: false }
}]
}
);
The place where I'm executing:
Game.findOneAndUpdate(
{ _id: gameId, 'players.id': client.id },
{ $push: { 'players.$.rounds': values } }, function(err) {
if (err) {
console.log('ERROR when submitting round');
console.log(err);
}
});
It prints me no error, but the db document is not affected. Still zero items in players.rounds.
you need to change your schema Object. we need to specify {strict: false} for changing the inserted documents in mongoose.
const gameSchema = new mongoose.Schema(
{
categories: [
{ type: String }
],
countdown: Number,
players: [{
_id: false,
id: String,
rounds: [
{ type: Map, of: String }
],
score: { type: Number, default: 0 },
ready: { type: Boolean, default: false }
}]
}, {strict:false} );
Model Schema
const PollSchema = new Schema({
title: { type: String, trim: true, required: true },
choices: [
{
title: { type: String, trim: true, required: true },
votes: { type: Number, default: 0, min: 0 },
}
],
date: { type: Date, default: Date.now },
url: { type: String, required: true, unique: true },
})
Update call
async vote (pollId, choiceId, unvoteId = '') {
try {
await pollModel.update(
{ '_id': pollId, 'choices._id': choiceId },
{ $inc: { 'choices.$.votes': 1 } },
)
if (unvoteId) {
await pollModel.update(
{
"$and": [
{ '_id': pollId },
{ 'choices._id': unvoteId },
{ 'choices.votes': { $gt: 0 } }
],
},
{ $inc: { 'choices.$.votes': -1 } },
)
}
return await pollModel.findById(pollId)
} catch (e) {
throw new ApiError(
500, 'Error: Poll:Vote', e
)
}
}
I have been trying a plethora of combinations trying to get this to work. Voting +1 works as intended, but when trying to -1, the query conditions are not properly matched. I have tried $and, $elemMatch, plain object with the 3 conditions (according to the docs this is sufficient and implicitly means and too.
Whenever I send through an unvoteId, no matter which _id I choose in the array, it will always match the FIRST element that has $gt 0 votes. It is as if choices._id is completely ignored, and as soon as it meets a choice that has > 0 votes, it returns that for the $ positional param.
Is this intended? I assumed $and would only match if all 3 conditions were satisfied.
What I am trying to do is update the votes atomically using $inc, while also ensuring that when someone votes, they cannot bring the value below 0. As the mongoose validators do not get run during updates, I am trying to validate this via the query itself.
Try something like this.
pollModel.update({
_id: pollId,
choices: {
$elemMatch: {
_id: unvoteId,
votes: {
$gt: 0
}
}
}
}, {
$inc: {
"choices.$.votes": -1
}
})