i'm currently trying to reference a collection called items with the structure below
packageSchema = schema({
recipient: String,
contents: [{item :{type: mongoose.Schema.Types.ObjectId,
ref: 'items', required : true}, amount: String}]
Below is my code for getting one package via its id
getOnePackage : function(id,callback)
{
packageModel.findById(id,callback)
.populate('contents')
}
So when i call the above function i'm expecting to get this result
{
recipient : Dave
contents : [
{item : {
_id:5d2b0c444a3cc6438a7b98ae,
itemname : "Statue",
description : "A statue of Avery"
} ,amount : "2"},
{item : {
_id:5d25ad29e601ef2764100b94,
itemname : "Sugar Pack",
description : "Premium Grade Sugar From China"
} ,amount : "5"},
]
}
But what i got from testing in Postman is this :
{
recipient : Dave,
contents : []
}
May i know where did it went wrong? And also how do i prevent mongoose from automatically insert an objectId for every single element in the contents array....
Because element in contents array is object with item field so your populate should be:
.populate('contents.item')
Related
I am making a web app. Currently I am storing the messages inside messages columns like below.
I have a column called msges and I have messages as time as key and value details. I want to create a function in which I pass the time, It will return the details of it. Can anyone help me? I can get single field but I don't know how to get it through key value. This is my function.
function getMessageDetails(uname,time,callback){
global.users.find({"uname" : uname,"msges":time},
// {"friends.friendUname":1,_id:0},
{_id:0},
function(err,doc){
if(err){
callback(false,err,"Message not found.",null);
}else{
callback(true,null,"",doc);
}
}
);
}
Thanks in advance. :)
I'd personally try to model your data a bit diffrently, If you had:
{
_id: "123123",
//...
friends: [
{ friendName: "etc..."}
],
msges : [
{
time: "16:25:02",
from: "alizia",
title : "hi buddy",
read: true
},
{
time: "12:25:02",
from: "bob",
title : "hi bobby",
read: false
}
]
}
You'd be able to query the following data by:
db.users.find({_id: "123123", "msges.time" : "16:25:02"}, { "msges.$.from" : 1 })
and will just pull out the one msg based on the query:
{
"_id" : "123123",
"msges" : [
{
"time" : "16:25:02",
"from" : "alizia",
"title" : "hi buddy",
"read" : true
}
]
}
Currently the data in mogo via mongoose is as below. I want to be able to iterate options once I pull it out of mongo.
currently if I save this record to a variable “record". I would need to do record.options[0].option1.check, I want to avoid [0].
I want to be able to just iterate over an object and be able to do the following.
record.option1.choice1
record.option2.choice2
my schema is
var questionSchema = new mongoose.Schema({
question: String,
question_slug: String,
options: []
});
{
"_id" : ObjectId("5832609483bf491db3d8faa1"),
"question" : “What is the capital of Illinois?",
"question_slug" : “what-is-the-capital-of-illinois",
"options" : [
{
"option1" : {
"check" : "on",
"choice" : “Springfield"
},
"option2" : {
"check" : "",
"choice" : “Chicago"
}
}
],
"__v" : 0
}
You can't define the schema for record.option1.choice1 and record.option2.choice2 since option1 and option2 seems to be dynamic.
But you can avoid [0] for record.options[0].option1.check by defining options as Object in the schema instead of array as below.
Hence, you can iterate over the object record.options with record.options.option1 and record.options.option2 etc.
var questionSchema = new mongoose.Schema({
question: String,
question_slug: String,
options: {
type: Object
}
});
{
"_id" : ObjectId("5832609483bf491db3d8faa1"),
"question" : “What is the capital of Illinois?",
"question_slug" : “what-is-the-capital-of-illinois",
"options" : {
"option1" : {
"check" : "on",
"choice" : “Springfield"
},
"option2" : {
"check" : "",
"choice" : “Chicago"
}
},
"__v" : 0
}
I have a collection (users) containing some documents like so :
{
_id: ObjectId("56d45406be05db4022be51f9"),
morecontent : ""
},
{
_id: ObjectId("56d45406be05db3021be32e3"),
morecontent : ""
}
I would like to create a new document for every entry in the user collection.
The documents would be created from a notification object like this :
{
type: 'alert',
msg: 'This is important'
}
The collection notifications should look something like this :
{
_id: ObjectId("56d45406be05db3021bf20a1"),
someoldcontent: "This was here before the request"
},
{
_id : ObjectId("56d45406be05db4022be20b1"),
user: ObjectId("56d45406be05db4022be51f9"),
type: 'alert',
msg: 'This is important'
},
{
_id : ObjectId("56d45406be05db3021be32e3"),
user: ObjectId("56d45406be05db3021be32e3"),
type: 'alert',
msg: 'This is important'
}
Is there any way to do this in a mongodb request?
Thanks to professor79 for helping me a lot with the question.
After lots of effort, the query was found. We used the aggregation framework in order to succeed.
The only 2 aggregations needed are $project and $out. The $out will automatically take care of the new _id in the notification document.
Given this collection named user :
{
_id: ObjectId("56d45406be05db4022be51f9"),
morecontent : ""
},
{
_id: ObjectId("56d45406be05db3021be32e3"),
morecontent : ""
}
We want to create a notification containing the same msg and type field for every document in the user collection.
Each notifications will be in the notifications collection an will have as a reference its corresponding userId.
Here is the query to achieve such a result :
db.user.aggregate([
{
$project: {
userId: '$_id',
type: { $literal: 'danger' },
msg: { $literal: 'This is a message' },
},
},
{ $out: 'notifications' },
])
The output in notifications collection:
{
"_id" : ObjectId("56d6112e197b4ea11a87de1a"),
"userId" : ObjectId("56d45406be05db4022be51f9"),
"type" : "danger",
"msg" : "This is a message"
},
{
"_id" : ObjectId("56d6112e197b4ea11a87de1b"),
"userId" : ObjectId("56d45406be05db3021be32e3"),
"type" : "danger",
"msg" : "This is a message"
}
As we have some chat to clarify problem:
the steps are needed to perform this operation server side:
first step - match > get users id
project ids to new documents as required
out -> store output in notification collection
After my initial question:
Handling relationships in Mongo and Sails?
I managed to use this approach, however I now need to resolve this the way I originally thought. For example, I have my Photo and Category models & collections, but now my category also contains addresses and business details.
In my Photo model I have the following:
attributes: {
caption : { type : 'string' },
fid : { type : 'string' },
user : { model : 'user' },
categories : { model : 'category', type : 'array'}
}
In my Category model I have the following:
attributes: {
photo : { model: 'photo' },
category : { type: 'string'},
address : { type: 'string'},
phone : { type: 'integer'},
//Foreign Keys
categories : { collection: 'photo', via: 'categories', type : 'integer'}
}
Now I can get the categories in the Photo collection to show as an ObjectID if I removed the type array and just send a single ObjectID of a category, however in my case, a photo can have more than one Category.
If I try sending an array of ObjectID's in my query, they just show up in the database as a String array. Is there anyway I get store these as an array of ObjectID's instead?
Basically it's many to many relationship. You can use Waterline scheme like this:
Photo Model
attributes: {
caption : { type : 'string' },
fid : { type : 'string' },
user : { model : 'user' },
categories : { collection : 'category', via : 'photos'}
}
Category Model
attributes: {
photos : { collection: 'photo', via: 'categories' },
category : { type: 'string'},
address : { type: 'string'},
phone : { type: 'integer'},
}
I am trying to update a mongoose model. Having some difficulites. This is how my schema looks like right now.
I want a user to have a library which consists of many songs. Those songs can be in multiple users libraries. And can also be in multiple playlists of which a user can have several.
var LibrarySchema = new Schema({
user: Schema.ObjectId
});
var PlaylistSchema = new Schema({
title: String,
description: String,
//songs: [SongsSchema],
user: Schema.ObjectId
});
var SongsSchema = new Schema({
name: String,
artist: String,
album: String,
time: Number,
url: String,
gid: String,
location: String,
playlist: [{playlist_id:Schema.ObjectId, position: Number}],
library: [Schema.ObjectId]
});
Now I want to do something like check if the url already exists in the song schema (url is an index). If that song does not exist I want to add it with all the values. However, if the song exists I want to append the playlist and position its in and the library.
For example here is the query I am trying now:
Song.update({url: s.url, "playlist.playlist_id": playlistId}, {$set: {name: s.name, artist: s.artist, album: s.album, time: s.time, url: s.url}, $addToSet: {playlist: {playlist_id: playlistId, position: s.position}, library: libId}},{upsert: true}, function(err, data) {});
And this is a sample of the database stored:
{ "name" : "Kanye West - All Of The Lights ft. Rihanna, Kid Cudi", "artist" : "unknown", "album" : "unknown", "time" : 328, "url" : "HAfFfqiYLp0", "_id" : ObjectId("4f127923ce0de70000000009"), "library" : [ ObjectId("4f1203af23c98cfab1000006") ], "playlist" : [
{
"playlist_id" : ObjectId("4f127923ce0de70000000007"),
"position" : "1"
}
] }
{ "name" : "Kanye West - Heartless", "artist" : "unknown", "album" : "unknown", "time" : 221, "url" : "Co0tTeuUVhU", "_id" : ObjectId("4f127923ce0de7000000000a"), "library" : [ ObjectId("4f1203af23c98cfab1000006") ], "playlist" : [
{
"playlist_id" : ObjectId("4f127923ce0de70000000007"),
"position" : "2"
}
] }
{ "name" : "Kanye West - Stronger", "artist" : "unknown", "album" : "unknown", "time" : 267, "url" : "PsO6ZnUZI0g", "_id" : ObjectId("4f127923ce0de7000000000b"), "library" : [ ObjectId("4f1203af23c98cfab1000006") ], "playlist" : [
{
"playlist_id" : ObjectId("4f127923ce0de70000000007"),
"position" : "3"
}
] }
Now what I am trying to do is if the url for the song is not in the database it should add it with all the information. If it is not then it will add to the library (which each user has one of) the library id UNLESS it already contains that value.
That works pretty good. The problem I am having right now is when it finds the url I want it to add to playlist the playlistId of the current playlist UNLESS it is already in the array and if it is and was passed a new value for position (user can change the order of a playlist) it should change the value of the position.
Perhaps I am not modelling it in a proper way. Any tips would be awesome!
MongooseJS contains something called DBRef. I think you want to use that, instead of handling all the references yourself.
For inserting if something is not there, either do a lookup first and insert if needed, or use an upsert. Not sure if Mongoose supports Upserts though...