Query mongoose -- Finding all battle where opponet id equals or challanger id equals some_id - javascript

I trying to query my mongo db for all battles a player has played. I was wondering about the or operation in mongoose. I can't get it to work.
I have tried something like this:
var currentUser = req.params.player_id;
Battle.find({}).populate({
path: 'utfordrer motstander',
}).where('utfordrer.id').equals(currentUser).$or('motstander.id').equals(currentUser).exec(function (err, battle) {
if (err){
console.log(err);
}
else {
console.log(battle);
}
});
This is my battle schema:
var battleSchema = new mongoose.Schema({
utfordrer: {
id: {type: mongoose.Schema.Types.ObjectId, ref: "User"},
username: String,
score: Number,
ferdig: Boolean
},
motstander: {
id: {type: mongoose.Schema.Types.ObjectId, ref: "User"},
username: String,
score: Number,
ferdig: Boolean
},
spill:
{
id: {type: mongoose.Schema.Types.ObjectId, ref: "Game"},
navn: String,
beskrivelse: String
},
tidspunkt: Date
});

Battle.find({$or:[ {'utfordrer.id': currentUser}, {'motstander.id': currentUser}]}).exec(function (err, battle) {
if (err){
console.log(err);
}else{
console.log("===========UTFORDRINGER");
console.log(battle.length);
res.render("Battles/index", {antallUtfordringer: antall, battleId: utfordringBattleId});
}
});

Related

Creating a nested mongodb document using Apollo-graphql and mongoose

I am trying to create a restaurant mobile app using react native and for that I have used the following restaurant mongo model schema in the backend:
const restaurantSchema = mongoose.Schema({
uid: {type: String, default:uuid.v4,required: true, unique: true},
id: {type: String, unique: true},
name: {type: String, required: true, unique: true},
phone: {type: String, required: true, unique: true},
owner: {type: String, required: true},
address: {type: String, required: true, unique: true},
menu: [{
uid: {type: String, default:uuid.v4, unique: true},
id: {type: String, unique: true},
category_name: {type: String, unique: true},
subcategory: [{
uid: {type: String, default:uuid.v4, unique: true},
id: {type: String, unique: true},
subcategory_name: {type: String, unique: true},
item: [{
uid: {type: String, default:uuid.v4, unique:true},
item_name: {type: String, unique: true},
calories: {type: String},
type: {type: String, enum: ['VEGAN', 'VEG', 'NON_VEG']},
price: {type: String},
}]
}]
}]
},
{timestamps: true}
)
I want to run a mutation such that, starting with the category_name array, it should check for each of the subarrays that whether the specified entry already exists or not in a single flow
If for the category already exists then the mutation should check whether the subcategory exists or not and if the category or the sub-category doesn't exist, the resolver should create new entries.
The mutation I wrote is working for some parts like when I try to mutate twice, it creates a category and subcategory entry but not in a single mutation operation
My resolver-
addMenuItems: async(_, {menuItemInput:{restaurant_name,name,calories,type,price,category,subcategory}},context) => {
const user = await Auth.verifyToken(context,process.env.TOKEN_SECRET)
//console.log(String(user.id))
if (!user) {
throw new ApolloError('Session expired')
}
const present_user = await User.findOne({uid:user.id})
const valid_user = Rest.owner_checker(present_user.username,User)
if (!valid_user) {
throw new ApolloError('Only the owner is permitted to modify menu items!')
}
duplicate_item = Rest.duplicate_checker(name,restaurant_name,category,subcategory,Restaurant)
if (duplicate_item !== null) {
throw new UserInputError("This item already exists")
}
try {
const newMenuItemStatus = await Rest.Item_adder(Restaurant, [name,restaurant_name,calories,type,price,category,subcategory])
if (newMenuItemStatus === 'SUCCESS') {
console.log('New Item was added successfully')
const newMenuItem = await Restaurant.findOne(({name: restaurant_name},
{"menu":
{category_name: category,
"subcategory":
{"item": {
"$elemMatch": {"item_name": {"$in": name}}
}}
},
}))
return {
id: newMenuItem.id,
...newMenuItem._doc
}
}
} catch (error) {
throw new UserInputError('Item addition failed')
}
}
The mutation code:
static Item_adder = async (Restaurant, Payload) => {
const [name, restaurant_name,calories, type, price, category, subcategory] = Payload
const Restaurant_category = await Restaurant.findOne({name: restaurant_name,
"menu": {
"$elemMatch": {"category_name": {"$in": category}}}}
)
console.log("Abefore: ",Restaurant_category)
if (Restaurant_category == null) {
await Restaurant.updateOne(
{name: restaurant_name},
{"$push": {"menu": {category_name: category}}},
function (error, res) {
if (error) {
console.log(error)
}
else {
}
}
)
}
const Restaurant_subcategory = await Restaurant.findOne({name: restaurant_name,
"menu.subcategory": {
"$elemMatch": {"subcategory_name": {"$in": subcategory}}}}
)
console.log("B: ",Restaurant_subcategory)
if (Restaurant_subcategory == null) {
await Restaurant.updateOne(
{name: restaurant_name,
"menu": {category_name: category,
"$push": {"subcategory": {subcategory_name: subcategory}}}
},
function (error, res) {
if (error) {
console.log(error)
}
else {
console.log(res)
}
})
}
await Restaurant.updateOne({name: restaurant_name,
"menu":
{category_name: category,
"subcategory":
{subcategory_name: subcategory,
"$push": {"item": {item_name:name,
calories:calories,
type:type,
price:price}}}
},
function (error, res) {
if (error) {
console.log(error)
}
else {
console.log(res)
}
}
})
return 'SUCCESS'
}
Where am I going wrong? I tried several combinations of resolvers and mongoose update queries but I've got no luck so far.

Save array of ObjectId's using Mongoose's Schema

I have a Mongoose Schema like:
const Role = new Schema({
guildID: {
type: Schema.Types.ObjectId,
ref: 'guilds',
required: true
},
roles: {
owner: {
id: {
type: Number,
required: false
},
commands: [[Schema.Types.ObjectId]]
}
}
})
And a small function to test whether it saves the data as desired which contains:
const roleTest = new Role({
guildID: "61a679e18d84bff40c2f88fd",
roles: {
owner: {
id: 123456789
},
commands: [
"61af57d828b9fd5a07dbdcba",
"61af5a6728b9fd5a07dbdcbb",
"61af5ab728b9fd5a07dbdcbc"
]
}
})
roleTest.save((err, doc) => {
if (err) return res.sendStatus(500)
console.log('Done')
})
It saves everything correctly except the array ObjectIds (commands). What is going wrong here?
You've written the commands in schema with nested array. Try with single array:
{
commands: [Schema.Types.ObjectId],
}
Try this:
commands: [
{ type: mongoose.Schema.Types.ObjectId }
]

findByIdAndUpdate pull from array objects equal to a specific value

I want to remove one or more objects of type tweet from the timeline list within the user model. The tweet objects that I want to remove are those whose author id matches a specific id user._id.
I have tried this:
router.get("/follow/:userId", isLoggedIn, catchAsync(async (req, res) => {
try {
const currentUser = await User.findById(req.user._id).populate("timeline")
const user = await User.findById(req.params.userId).populate("followers tweets")
for (let tweet of currentUser.timeline) {
if (tweet.author._id.equals(user._id)) {
currentUser.timeline.pull(tweet._id)
}
}
req.flash("error", `Unfollowed to ${user.username}`)
user.save();
currentUser.save()
res.redirect(`/${user._id}`)
} catch (err) {
req.flash("error", err.message);
res.redirect("back")
}
}));
and this:
await User.findbyIdAndUpdate(currentuser._id, { $pull: { timeline: { author : user._id } } }
but none of them are working.
My user model:
const userSchema = new Schema({
name: {
type: String,
required: true
},
biography: { type: String, maxlength: 160 },
location: {type: String, maxlength: 30 },
email: {
type: String,
unique: true,
required: true
},
image: {
url: String,
filename: String,
},
followers: [{ type: Schema.Types.ObjectId, ref: "User" }],
following: [{ type: Schema.Types.ObjectId, ref: "User" }],
tweets: [{ type: Schema.Types.ObjectId, ref: "Tweet"}],
timeline: [{ type: Schema.Types.ObjectId, ref: "Tweet"}]
});
My tweet model :
const tweetSchema = new Schema({
images: [{
url: String,
filename : String
}],
text: { type: String, maxlength: 260},
date: { type: Date, default: Date.now },
author: { type: Schema.Types.ObjectId, ref: "User" },
parent: { type: Schema.Types.ObjectId, ref: "Tweet", default:null },
replies: [{ type: Schema.Types.ObjectId, ref: "Tweet" }],
likes: [{ type: Schema.Types.ObjectId, ref: "User" }],
retweets: [{ type: Schema.Types.ObjectId, ref: "Tweet" }],
retweetStatus: {type: Schema.Types.ObjectId, ref: "Tweet", default: null}
});
If your collection looks like this:
[
{
"_id" : ObjectId("60254276259a60228cbe5707"),
"name" : "Mary",
"timeline" : [
ObjectId("60254276259a60228cbe5703"),
ObjectId("60254276259a60228cbe5704"),
ObjectId("60254276259a60228cbe5705")
]
},
{
"_id" : ObjectId("60254276259a60228cbe5706"),
"name" : "Dheemanth",
"timeline" : [
ObjectId("60254276259a60228cbe5700"),
ObjectId("60254276259a60228cbe5701"),
ObjectId("60254276259a60228cbe5702")
]
}
]
then the solution is:
usersSchema.updateOne(
{
"_id": ObjectId("60254276259a60228cbe5706"),
"timeline": ObjectId("60254276259a60228cbe5700"),
},
{
$pull: {
"timeline": ObjectId("60254276259a60228cbe5700")
}
}
)
.then()
.catch()
// or
usersSchema.findOneAndUpdate(
{
"_id": ObjectId("60254276259a60228cbe5706"),
"timeline": ObjectId("60254276259a60228cbe5700"),
},
{
$pull: {
"timeline": ObjectId("60254276259a60228cbe5700")
}
},
{
new: true
}
)
.then()
.catch()
I finally found the issue! The problem I was having is that I was trying to remove items from a list of objects while looping through that list. The solution is easy: you can just create an auxiliar empty array and push the items that you want to remove, then loop through that auxiliar array and pull the items from the original array.
In my case, I've already had an array with the tweets that I wanted to remove, user.tweets. The solution is:
router.get("/follow/:userId", isLoggedIn, catchAsync(async (req, res) => {
try {
const currentUser = await User.findById(req.user._id).populate("timeline")
const user = await User.findById(req.params.userId).populate("followers tweets")
for (let tweet of user.tweets) {
currentUser.timeline.pull(tweet._id)
}
req.flash("error", `Unfollowed to ${user.username}`)
user.save();
currentUser.save()
res.redirect(`/${user._id}`)
} catch (err) {
req.flash("error", err.message);
res.redirect("back")
}
}));

How do you save certain items for specific users in mongodb?

I'm working on a job tracker app.
User creates an account, saving the user in a mongodb collection.
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
const JobSchema = new mongoose.Schema({
position: {
type: String,
required: true
},
company: {
type: String,
required: true
},
status: {
type: String,
default: "applied"
},
date: {
type: Date,
default: Date.now
}
});
When a user adds a job, how would you store (.post) and retrieve (.get) that data to correspond to that specific user only?
Is there a way to save the users "_id" to the jobs added, and searchById to get the jobs?
It depends what exactly you want to achieve meaning what type of relationships your models will have. Lets say your users will have multiple jobs the best approach would be to store an array of ObjectIds. The refoption tells mongoose which collections to search during population of the array
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
jobs: [{type:Schema.Types.ObjecId,ref: 'Job'}]
});
and then when you query the database you chain populate('jobs') after the query.
You can read more on the subject here
For example,
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
const User = mongoose.model('User', UserSchema);
async function updateUser() {
let user = await User.findOne({"name": "a-unique-user-name-in-the-db"})
let userId = user._id
let newEmail = "asdf#asdf.com"
let updated = await User.updateOne(
{ "_id": userId },
{
$set: {
"email": newEmail,
}
}
)
if (updated) {
console.log("updated")
}
}
updateUser();

Mongo populate in optional field giving cast error

I have a 'vendor' and 'media' collection, media collection store vendor profile images and that is not mandatory field for vendors. Some vendors have profile picture some not, I want to list all vendors including their profile pictures reference. But I'm getting cast error when I populate profilePicture from meidas. I have other populate like 'userId', 'venueId' those are mandatory fields and it works.
Error:
CastError: Cast to ObjectId failed for value "xyz" at path "_id" for model "medias" undefined
Find Query:
const result = await resultObject.skip(skip)
.populate('userId')
.populate('venueId')
.populate('profilePicture')
.limit(parseInt(obj.pageSize, 10))
.sort({ [obj.sortColumn]: parseInt(obj.sortValue, 10) });
return result;
medias model
const MediasModel = () => {
const MediasSchema = new mongoose.Schema({
url: { type: String, required: true },
key: { type: String},
}, { timestamps: { createdAt: 'createdDate', updatedAt: 'modifedDate' } });
return mongoose.model('medias', MediasSchema);
};
module.exports = MediasModel();
vendors model
const Vendors = new mongoose.Schema({
venueId: { type: mongoose.Schema.Types.ObjectId, ref: 'venues' },
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'users' },
name: { type: String, required: true },
profilePicture: { type: mongoose.Schema.Types.ObjectId, ref: 'medias' },
}, { timestamps: { createdAt: 'createdDate', updatedAt: 'modifedDate' } });
module.exports = mongoose.model('vendors', Vendors);
Try the below code
const Vendors = require('path/to/model_vendor');
Vendors.find()
.populate([{path: 'venues'}, {path: 'users'}, {path: 'medias'}])
.skip(skip_value)
.limit(limit_value)
.sort({condition: 1 }) // Modify according to your need
.exec().
.then(vendors=>{
console.log(vendors)
}).catch(err=>{
console.log(err)
})

Categories

Resources