so I have this kind of model
const vetSchema = new mongoose.Schema({
username: {type: String, required: true, trim: true, unique: true},
email: {type: String, unique: true, trim: true,},
expYear: {type: Number},
KTP: {type: String, unique: true, trim: true},
cert_id: {type: String, unique: true, trim: true, select: false},
})
const clinicSchema = new mongoose.Schema({
vet: [{type: mongoose.Schema.Types.ObjectID, ref: 'vet'}],
)}
what I want to do is finding vet by username, which the vet ID is not included in the clinic based on clinic ID, the query to find the vet is {username: {$regex: (?i)${keyword}.*}}
for example, we have this data
Clinic = [{
"_id" : ObjectId("5e57a45836d300b188f4444a"),
"vet": [ObjectId("5e0742fc9d4b20100f89b626"),ObjectId("5e53698fd2b9ee43e7693e01")]
}]
Vet = [
{
"_id" : ObjectId("5e0742fc9d4b20100f89b626"),
"username": "VetClinic"
},
{
"_id" : ObjectId("5e55df62576bc9811877033e"),
"username": "VetNotClinic"
},
{
"_id" : ObjectId("5e53698fd2b9ee43e7693e01"),
"username": "VetClinic"
},
]
what i want is if I find Vet it only shows VetNotClinic because VetClinic is included in the clinic's ID, any good query / agregate?
you can use $nin to query where a field is "not in" an array like so
Vet.find({
username: {$regex: (?i)${keyword}.*},
_id: {$nin: clinic.vet}
})
Related
So, I have this kind of model
const produkSchema = new mongoose.Schema({
nama_produk: String,
etalase: {type: mongoose.Schema.Types.ObjectID, ref: 'kategori'},
kategori: {type: mongoose.Schema.Types.ObjectID, ref: 'kategori'},
jenis: {type: mongoose.Schema.Types.ObjectID, ref: 'kategori.jenis'},
bahan: String,
warna: String,
deskripsi: String,
foto_produk: [String],
harga: Number,
link_bukalapak: String,
link_shopee: String,
link_tokopedia: String,
}, {
weights: {
nama_produk: 5,
},
timestamps: true
})
const tokoSchema = new mongoose.Schema({
username: {type: String, trim: true},
password: {type: String, required: true, select: false},
merek: String,
listMerek: [{type: mongoose.Schema.Types.ObjectID, ref: 'produk'}],
deskripsi: String,
follower: [{type: mongoose.Schema.Types.ObjectID, ref: 'user'}],
email: {type: String, trim: true, unique: true},
instagram: String,
whatsapp: String,
website: String,
alamat: String,
foto_profil: String,
bukalapak: String,
shopee: String,
tokopedia: String,
fotoktp: String,
banner: [{
gambar: {type: String, required: true, trim: true},
order: {type: Number, required: true},
}],
produk: [produkSchema],
etalase: [{type: mongoose.Schema.Types.ObjectID, ref: 'kategori'}],
approve: {type: Number, default: 0}, // 0: pending, 1: reject, 2: approve
populer: {type: Boolean, default: false},
}, {timestamps: true});
exports.toko = mongoose.model("toko", tokoSchema);
const jenisSchema = new mongoose.Schema({
label: String,
gambar: String,
}, {timestamps: true})
const kategoriSchema = new mongoose.Schema({
label: String,
gambar: String,
jenis: [jenisSchema]
}, {timestamps: true});
so what I want to join is, toko.produk.jenis with kategori.jenis, but as you know, mongoose can't populate between subdocument, I have tried toko.find().populate("produk.jenis", "label") but it showing error Schema hasn't been registered for model "kategori.jenis". Use mongoose.model(name, schema) any query suggestions? I've tried
{
$lookup: {
"from": "kategoris",
"localField": "produk.jenis",
"foreignField": "jenis",
"as": "jenisnya"
}
}
but it doesn't seem work, and returning an empty array instead. What should I do? Should I rearrange my schema?
You can try this,
$match your conditions
$unwind deconstruct produk array
$lookup with pipeline
$unwind deconstruct jenis array
$match match jenis._id
$project to show only _id and label
$unwind deconstruct in path produk.jenisnya
$group by _id and push in to produk
db.toko.aggregate([
{ $match: { _id: ObjectId("5f1d77aca53cb13980324c73") } },
{ $unwind: "$produk" },
{
$lookup: {
from: "kategoris",
as: "produk.jenisnya",
let: { pjid: "$produk.jenis" },
pipeline: [
{ $unwind: "$jenis" },
{ $match: { $expr: { $eq: ["$$pjid", "$jenis._id"] } } },
{ $project: { "jenis._id": 1, "jenis.label": 1 } }
]
}
},
{ $unwind: { path: "$produk.jenisnya" } },
{
$group: {
_id: "$_id",
produk: { $push: "$produk" },
// you can add otehr fields as well like alamat
alamat: { $first: "$alamat" }
}
}
])
Playground
I have a User Schema, which has multiple notes, and the Note which belongs to a userId
const UserSchema = new Schema({
_id: Schema.Types.ObjectId,
email: {type: String, required: true, trim: true, lowercase: true, unique: true},
notes: [{type: Schema.Types.ObjectId, ref: 'Note'}]
});
const NoteSchema = new Schema({
userId: {type: mongoose.Types.ObjectId, ref: 'User'},
content: {type: String, required: true, trim: true, lowercase: true},
});
I'm trying to populate my User with the notes using the following syntax (from the docs)
const user = await User.findById(mongoose.Types.ObjectId("5bd2a8c4963ac00f57a18074"))
.populate('notes')
.exec(function (err, result) {
console.log(result);
});
But it's returning the User without the Notes data. Any idea what I might be doing wrong?
NoteSchema here is the problem:
userId: {type: mongoose.Types.ObjectId, ref: 'User'}
Use below,
userId: {type: mongoose.Schema.Types.ObjectId, ref: 'User'}
// OR
userId: {type: Schema.Types.ObjectId, ref: 'User'}
// OR
userId: {type: Schema.ObjectId, ref: 'User'} // For backword compatibility
Note:- The schema should always use mongoose.Schema.Types. And mongoose.Types.ObjectId can be used withing mongoose implementation.
I am able to get document properly (Below code):
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
const NoteSchema = new Schema({
userId: {type: Schema.Types.ObjectId, ref: 'UserTest'},
content: {type: String, required: true, trim: true, lowercase: true},
});
const UserSchema = new Schema({
_id: Schema.Types.ObjectId,
email: {type: String, required: true, trim: true, lowercase: true, unique: true},
notes: [{type: Schema.Types.ObjectId, ref: 'NoteTest'}]
});
var Note = mongoose.model('NoteTest', NoteSchema);
var User = mongoose.model('UserTest', UserSchema);
User.find({_id : mongoose.Types.ObjectId("5bd2c84dd79cc5d8b1c62964")})
.populate('notes')
.exec(function (err, result) {
console.log("result.....", JSON.stringify(result));
});
Output:
[
{
"_id": "5bd2c84dd79cc5d8b1c62964",
"email": "hardik#com.com",
"notes": [
{
"_id": "5bd2c869d79cc5d8b1c62965",
"content": "ABC",
"userId": "5bd2c84dd79cc5d8b1c62964"
},
{
"_id": "5bd2c88ad79cc5d8b1c62966",
"content": "DEF",
"userId": "5bd2c84dd79cc5d8b1c62964"
}
]
}
]
I'm using mongoose and I'm trying to get activities from the schema 'Activity' with an specific filter using $geoNear, but it always returns an empty array and I think it's because the aggregate function is not finding the coordenates of my model.
This is an example of the JSON to send:
{
"coordinates": {
"lat": 37.3890924,
"lon": -5.984458899999936
},
"distance": 100000000
}
This is the query:
Activity.aggregate([
{ $geoNear: {
near: {
type: "Point",
coordinates: [req.body.coordinates.lon, req.body.coordinates.lat]
},
maxDistance: req.body.distance * 1000,
spherical: true,
distanceField: "distance"
}
}
])
And this is the schema, where the coordinates are into the field 'meetingPoint':
const mongoose = require('mongoose');
const mongoosePaginate = require('mongoose-paginate');
const Schema = mongoose.Schema;
var ActivitySchema = Schema({
title: {type: String, require: true },
meetingPoint: {
meet_name:{type: String, require: true },
coordinates: {
lat: {type: Number, require: true },
lon: {type: Number, require: true }
}
},
date: {type: Date, require: true },
car: Boolean,
sites: {type: Number, min: 0 },
price: {type: Number, min: 0.0, require: true },
description: String,
eventTime: String,
event: Boolean,
sport: {type: Schema.Types.ObjectId, ref: 'Sport', require: true },
owner: {type: Schema.Types.ObjectId, ref: 'User', require: true },
attenders: [{type: Schema.Types.ObjectId, ref: 'User'}],
comments: [{type: Schema.Types.ObjectId, ref: 'Comment'}],
ratings: [{
rating:{type: Number},
user: {type: Schema.Types.ObjectId, ref:'User'}
}],
creationDate: {type: Date, default: Date.now, require: true },
updateDate: {type: Date, default: Date.now, require: true },
public: Boolean,
image: String
});
ActivitySchema.plugin(mongoosePaginate);
ActivitySchema.index({location: "2dsphere"});
module.exports = mongoose.model('Activity', ActivitySchema);
EDIT: I changed the coordinates in mongoose schema to the GeoJSON format(I think) and now they look like this:
meetingPoint: {
meet_name:{type: String, require: true },
coordinates: {
type: String,
coordinates: []
}
}
But the result is the same.
EDIT2: I also updated the existing data in the collection according to the meetingPoint with the pertinent format. This is an example:
"_id" : ObjectId("5ac36a2aasdsd3242b"),
"meetingPoint" : { "meet_name" : "Av. de Menéndez Pelayo, 76, 41030 Madrid, España", "coordinates" : { "type" : "Point", "coordinates" : [ -5.984458899
9936, 37.3890924 ] } },
"attenders" :....
But I still receive no activities with the filter.
Trying to do a simple CRUD for a user.
I am passing name, email, password, location, avatar through a sign up form from React/Redux.
I am getting an error during the save which says the following about a duplicate key error --
(node:30190) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): WriteError({"code":11000,"index":0,"errmsg":"E11000 duplicate key error index: heroku_10vr0vgl.users.$googleId_1 dup key: { : null }","op":{"avatar":"avatar.jpg","slug":"jane","id":"cj7nl39w50000amcaool50zcp","name":"Jane","email":"admin#jane.com","password":"$2a$10$envMKYq6xFCkZGpYVd4rEel4g5TGijFOEnr.ayMymHM1ph0/1luGC","location":"Los Angeles","_id":"59bd5e9478537875ee6b8939","createdAt":"2017-09-16T17:25:40.863Z","campaigns":[],"role":"NORMAL","__v":0}})
Looks to be something about a duplicate val, but googleID for ex is not required.
I only have a mock user in the user collection that looks like the following --
[
{
"_id": {
"$oid": "59a070dea4de3af502af7d5c"
},
"avatar": "avatar.jpg",
"name": "John Doe",
"role": "ADMIN",
"slug": "john-doe",
"id": "1",
"email": "admin#johndoe.com",
"location": "Los Angeles",
"campaigns": ["1"],
"twitterId": "refinery29",
"password": "test1234"
}
]
The user model looks like the following --
import mongoose from 'mongoose';
const Schema = mongoose.Schema;
const userSchema = new Schema({
name: {type: 'String', required: true},
role: {type: 'String', default: 'NORMAL', required: true},
location: {type: 'String'},
slug: {type: 'String', required: true, index: {unique: true, dropDups: true}},
campaigns: {type: ['String'], default: []},
avatar: {type: 'String', required: true},
email: {type: 'String', index: {unique: true, dropDups: true}},
id: {type: 'String', required: true, index: {unique: true, dropDups: true}},
googleId: {type: 'String'},
facebookId: {type: 'String'},
twitterId: {type: 'String'},
createdAt: {type: 'Date', default: Date.now, required: true},
password: {type: 'String'},
});
export default mongoose.model('User', userSchema);
Looks like I had an existing index reference. I dropped my user collection and saved. All is well!
I have:
let userSchema = mongoose.Schema({
email: {type: String, required: true, unique: true},
passwordHash: {type: String, required: true},
fullName: {type: String, required: true},
salt: {type: String, required: true},
ads: [{type: ObjectId, ref: 'Ad'}],
roles: [{type: String}]
}
let adSchema = mongoose.Schema({
author: {type: ObjectId, ref: 'User'},
title: {type: String, required: true},
category: {type: ObjectId, ref: 'Category', required: true},
town: {type: ObjectId, ref: 'Town', required: true},
}
);
let categorySchema = mongoose.Schema({
name: {type: String, required: true, unique: true},
ads: [{type: ObjectId, ref: 'Ad'}]
}
);
let townSchema = mongoose.Schema({
name: {type: String, required: true, unique: true},
ads: [{type: ObjectId, ref: 'Ad'}]
}
);
I want to find for example town by id and remove all ads in it(and ofcourse to remove the ads from their categories and authors).How can i do that?
I would suggest bulk getting the array of object Ids and using it like this:
Ad.remove({_id: {$in: Ad_ids_array}}, function(){...}); // and so on
You can add a pre-remove hook in the ad schema definition like this:
adSchema.pre('remove', function(next) {
let lethis = this;
// Pull ad out of all the Category docs that reference the removed ad.
this.model('Category').update({}, { $pull: {ads: lethis._id}}, { safe: true }, next);
// Pull ad out of all the User docs that reference the removed ad.
this.model('User').update({}, { $pull: {ads: lethis._id}}, { safe: true }, next);
});
This will remove the ad from the categories and users that have it in their ads array.