Display items from MongoDB to FrontEnd - mongodb

I have a nested array in MongoDB database that I wish to display on the frontend using Jade and Express.
I am having some trouble displaying them:
This is the nested items I wish to display:
MongoDB:
{
"_id" : ObjectId("5c3343913d1e1323111fce6f"),
"title" : "Projecten",
"__v" : 0,
"sub_items" : [
{
"title" : "item1"
},
{
"title" : "item2"
}
]
}
Mongoose Model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var menuItems = new mongoose.Schema({
sub_items : {
title: String
}
}, {collection: 'menu_items'});
module.exports = mongoose.model("menu_items", menuItems);
I post the nested items with Express like this:
postController.updateSubItems = function(req,res,item) {
var id = req.body.id;
var saveData = {
title: req.body.sub_item
};
item.update({_id: id}, {$addToSet:{sub_items: saveData}}, (err, result) => {
});
};
Display in jade like this:
each item in data
p #{item.sub_items}
Eventually it comes out like this:
item1,item2
Like a string, though I want to display them like single items

Try below code, as per your sub_items object
each item in [{sub_items:'sub_item_1'}]
p=item.sub_items
Paste above code into this editor

Not sure if there's a more elegant way to do this in Jade, but I just used the editor suggested by #iamwebkalakaar, tested the following snippet and it appears to print correctly:
each item in [{"sub_items" : [{"title" : "item1"}, {"title" : "item2"}]}]
each subitem in item.sub_items
p=subitem.title
New snippet
- var data = { "title" : "Projecten", "__v" : 0, "sub_items" : [ { "title" : "item1" }, { "title" : "item2" } ] };
each subitem in data.sub_items
p=subitem.title

Related

Mongoose object schema: How do I declare schema in mongoosejs to be able to iterate an options field?

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
}

How to set result of query as array with mongoose/mongodb

I need to set the result of a query as an array of an object being saved.
First I get the Items:
Item.find({...}, function...
which looks like that:
data =
[ { foo: [],
bar: true,
_id: 564f62b1659abdc22b9dd1da },
{ foo: [],
bar: true,
_id: 564f76b628bd4b62335bad7c } ]
Now I create an object which I want to save with the _ids of the query result as an "Item" ref array:
var itemholder = new Itemholder(req.body);
itemholder.items = ????
Itemholder has an array of "Item" refs called "items" which should look like this:
"items" : [ { "item" : ObjectId("564f62b1659abdc22b9dd1da"),
"_id" : ObjectId("564f54c4e9bbbbee230647a4") },
{ "item" : ObjectId("564f76b628bd4b62335bad7c"),
"_id" : ObjectId("564f67043f88a5b12d6c32ff") } ]
Thank you.
Found a way to do it (probably not the best):
Item.find(..., function(err, data){
if(err){
...
}else{
data = data.map(function(data) { return {'item': data._id}; });
sprint.items = data;
sprint.save(function(err2, data2){
...

Mongo nested query with keys

Need help on MongoDB nested query. Below is my mongo collection.
Preference collection
{
"_id" : "user123",
"preferences" : {
"product-1" : {
"frequency" : "Weekly",
"details" : {
"email" : {
"value" : "On"
}
}
},
"product-2" : {
"preferencesFor" : "mpc-other",
"preferencesForType" : "Product",
"details" : {
"email" : {
"value" : "Off"
}
}
},
"product-3" : {
"preferencesFor" : "mpc-other",
"preferencesForType" : "Product",
"details" : {
"email" : {
"value" : "On"
}
}
}
}
}
Product Collection
{
"_id" : "product-1",
"name" : "Geo-Magazine"
}
{
"_id" : "product-2",
"name" : "History-Magazine"
}
{
"_id" : "product-3",
"name" : "Science-Magazine"
}
product-1, product-2... are keys from a Map.
The keys are stored in another collection Product Collection.
Can I create a nested query to cross-reference the product keys from another table?
I need the output in the below table format. Please suggest.
user123 product-1 email On
user123 product-2 email Off
user123 product-3 email On
I tried the below but can't get result. Please suggest.
var cursor = db.productSummary.find();
while(cursor.hasNext()){
var sku = cursor.next()._id;
var skuCol = "preferences."+sku+".details.email";
var skuVal = "preferences."+sku+".details.email.value";
db.marketingPreferences.find( {}, {_id:1, skuCol:1, skuVal:1});
}
> var myCursor = db.productSummary.find();
> while(myCursor.hasNext()){
var sku = myCursor.next()._id;
var skuCol = "preferences."+sku+".details.email";
var skuVal = "$preferences."+sku+".details.email.value";
var result = db.marketingPreferences.aggregate([{"$project":{"_id":1,value:skuVal,preferences:{$literal: sku}}}],{allowDiskUse: true});
while(result.hasNext()){
printjson(result.next());
}
}
Result
{ "_id" : "user123", "preferences" : "product-1", "value" : "On" }
{ "_id" : "user123", "preferences" : "product-2", "value" : "Off" }
{ "_id" : "user123", "preferences" : "product-3", "value" : "On" }
There's a difference between MongoDB and normal SQL DB. Firstly, when you query a MongoDB collection, it doesn't return a row as it will in a SQL db. What you get here is a document similar to JSON.
Also when you use preferences.product-1.details.email : 1 it wont return you the word 'email', rather it will return you the value ie. {"value" : "On" }.
Using this: db.preference.find({},{"_id":1,"preferences.product1.details.email.value":1})
you will be able to get two details which are user123 and On and you can get product-1 from your previous query. You can store these values in a variable and keep printing them to obtain the table necessary. Also you would need another cursor to store the result of the second second query that you would do.
Here's what your query will produce if it was single standalone query:
> db.preference.find({},{"_id":1,"preferences.product1.details.email.value":1})
.pretty()
{
"_id": "user123",
"preferences": {
"product-1": {
"details": {
"email": {
"value": "On"
}
}
}
}
}
public static void test(){
MongoCollection<Document> collection = getDatadase().getCollection("product");
MongoCollection<Document> pref = getDatadase().getCollection("pref");
List<Document> allDocList = collection.find().into(new ArrayList<Document>());
for(Document doc:allDocList){
System.out.println(doc.get("_id"));
String preferences = doc.get("_id")+"";
String sku = "$preferences."+preferences+".details.email.value";
Document aggregation = new Document().append("$project", new Document().append("_id", 1).append("value", sku));
List<Document> pipeline = new ArrayList<Document>();
pipeline.add(aggregation);
List<Document> aggList = pref.aggregate(pipeline).into(new ArrayList<Document>());
for(Document doc1:aggList){
System.out.println(doc1.append("preferences", preferences));
}
}
}
This Will return
product-1
Document{{_id=user123, value=On, preferences=product-1}}
product-2
Document{{_id=user123, value=Off, preferences=product-2}}
product-3
Document{{_id=user123, value=On, preferences=product-3}}

add subitems to meteor document

I have a meteor collection "list" that has the following data structure.
"list" : [
{
"_id" : "id",
"author" : "authorId",
"createdOn" : "DateTime",
"description" : "description",
"items" : [
{
"item1" : {
"itemComplete" : "Boolean",
"itemName" : "item name",
"itemDescription" : "item description",
}
},
{
"item2" : {
"itemComplete" : "Boolean",
"itemName" : "item name",
"itemDescription" : "item description",
}
}
],
Users will be able to add arbitrary number of list items. I am trying to figure out how to add itemX programmatically. E.g. I have the following code (which does not work) that gives an idea of what I am trying to accomplish.
var currentItemCount = Lists.find({_id:_currentListId, items:{}}).count() + 1;
var newItemNum = "item" + currentItemCount;
var newListItem = $("#list-item").val();
Lists.update({_id:_currentListId},{$push : {items:{newItemNum:{itemName:newListItem}}}});
I would appreciate any suggestions or hints to help me fix my code. Please let me know if I am missing some information.
Thanks in advance.
Kamal
Give something like this a try:
// fetch the current list
var list = Lists.findOne(_currentListId);
// find the number of existing items and handle the case where there are none
var numItems = (list.items || []).length;
// the the next item key will be one more than the length
var itemKey = 'item' + (numItems + 1);
// extract the item name from a form
var itemValue = {itemName: $('#list-item').val()};
// you can't use varaiable names as keys in object literals
// so we have to use bracket notation
item = {};
item[itemKey] = itemValue;
// push the new item onto the list of items
Lists.update(_currentListId, {$push: {items: item}});

Mongodb query (hashmap objects)

I want to query all the UserGroup's ID where admins's ID="25160228446835585906563830293" or users's ID ="25160228446835585906563830293".
this is a hashmap key and value pair in java obj hashmap<String,Date>
"25160228446835585906563830293" : ISODate("2013-03-26T04:51:36.731Z")
{ "_id" : ObjectId("51512958849ca4748271c640"),
"_class" : "com.pcd.app.model.UserGroup",
"groupName" : "sdfsadfsad",
"privacyType" : "PRIVACY_OPEN",
"approvalType" : "MEMBER_APPROVAL",
"groupDescription" : "test",
"admins" : {
"25160228446835585906563830293" : ISODate("2013-03-26T04:51:36.731Z"),
"25160228446835585906563830294" : ISODate("2013-03-26T04:51:36.731Z"),
"25160228446835585906563830295" : ISODate("2013-03-26T04:51:36.731Z")
},
"users" : {
"25160228446835585906563830296" : ISODate("2013-03-26T04:51:36.731Z")
}
}
I'd suggest you restructure your document to make it indexable and more easily searched in MongoDB.
Instead of using the id of the admin as a field, add each admin as an object of an array:
"admins" : [
{ id: "25160228446835585906563830293",
date: ISODate("2013-03-26T04:51:36.731Z") }
],
This will make searches more natural:
db.so.find( { "admins.id" :
{ $in: ['25160228446835585906563830293',
'25160228446835585906563830296']}})
You can use the $in (docs) operator to look for admins with an id that matches the list as you wanted (admins.id).
So, given a Java QueryBuilder, it might look something like this:
BasicDBList adminIds = new BasicDBList();
adminIds.addAll(ids); // the ids could be a List<String>
DBObject inClause = new BasicDBObject("$in", adminIds);
DBObject query = new BasicDBObject("admins.id", inClause);
You may want to use ensureIndex to build an index (docs).
Based on your original example, here's the full document for reference:
{
"_id" : ObjectId("51512958849ca4748271c640"),
"_class" : "com.pcd.app.model.UserGroup",
"groupName" : "sdfsadfsad",
"privacyType" : "PRIVACY_OPEN",
"approvalType" : "MEMBER_APPROVAL",
"groupDescription" : "test",
"admins" : [
{ id: "25160228446835585906563830293" ,
date: ISODate("2013-03-26T04:51:36.731Z") },
{ id: "25160228446835585906563830294" ,
date: ISODate("2013-03-26T04:51:36.731Z") },
{ id: "25160228446835585906563830295" ,
date: ISODate("2013-03-26T04:51:36.731Z") }
],
"users" : [
{ id: "25160228446835585906563830296",
date : ISODate("2013-03-26T04:51:36.731Z") }
]
}
If you are using mongodb java driver you can do the following:
BasicDBObject queryForAdminsID = new BasicDBObject("admins." + adminsID, new BasicDBObject("$exists", true));
// BasicDBObject queryForUsersID = new BasicDBObject("users." + usersID, new BasicDBObject("$exists", true));
cursor = coll.find(query); // coll is a DBCollection
try {
while(cursor.hasNext()) {
System.out.println(cursor.next());
}
} finally {
cursor.close();
}
where usersID and adminsID are your ids