For example I have 50 users and I have collection like
Rooms = new Mongo.Collection('rooms');
First I want to mix Users like if I have this [id1,id2,id3...] make it this [id52,id91241,id2...]
and after put in every Room 5 users like
for (i=0;i<countofmyusers;i=i+5)
crete new room and put 5 users // ?? how .. Rooms.insert(??)
{
users: [id1,id44,id2451,id921241,id23]
...
}
Any idea how to do it ?
Here's an example function that creates a set of rooms, each with a random sample of users:
var randomRooms = function(roomCount, sampleSize) {
// extract all of the user ids in the datbase
var userIds = _.pluck(Meteor.users.find({}, {fields: {_id: 1}}).fetch(), '_id');
// create roomCount rooms
_.times(roomCount, function() {
// insert a new room with a random sample of users of size sampleSize
Rooms.insert({users: _.sample(userIds, sampleSize)});
});
};
Here's a new version which enforces that user ids not be repeated across groups (i.e. each user will be assigned to one and only one group):
var randomRooms = function(userCountInEachRoom) {
// extract all of the user ids in the datbase
var userIds = _.pluck(Meteor.users.find({}, {fields: {_id: 1}}).fetch(), '_id');
// create a new array of randomly sorted user ids
var shuffledUserIds = _.shuffle(userIds);
// create a list of lists of user ids where each list has at most
// userCountInEachRoom ids - note that users will not be repeated in any lists
var userLists = [];
while (shuffledUserIds.length > 0)
userLists.push(shuffledUserIds.splice(0, userCountInEachRoom));
// insert a new group for each sub-array of user ids
_.each(userLists, function(users) {
Rooms.insert({users: users});
});
};
You'd call it like randomRooms(5) to place at most five users in each group. Note that the last group will have fewer than five users if the total user count is not a multiple of five.
Related
I am creating an iOS application to help users who collect figurines keep track of their figurines and see realtime price information.
I have two collections:
The "master" collection
This is essentially a catalog of thousands of figurines users can select to add to their collection. It has information about each item, such as Artist, Original Price, Barcode, Year, Comments, etc.
The "user" collection
This contains documents for each user. Each of these "user" documents has a sub-collection with documents for each figurine they have added to their collection.
Currently, if a user wants to add a new item to their personal collection, they go to the "master" collection UITableView and swipe to add an item. The item document is basically copied from the "master" collection and a new document in the user sub-collection is created. They can then go to a UITableView that displays the items they have added. They have the option to add their own information about the item, such as comments, date bought, date sold, price bought, etc.
My question: How can I sync information between the document in the user collection/sub-collection and the document in the main collection? Say the "Market Price" for an item has gone up, so I update the main collection database. How can I get this price change to display in all users' collections?
I assume by using Cloud Functions, but I wanted to post here in case there was an easier method.
This is definitely a good use for Cloud Functions. Create an onUpdate trigger for your /users{uid}/figurines/{figurineId} collection and then use that to copy the updated data to the master.
You can either copy specific fields or you can check for differences by examining event.data.data() and event.data.previous.data()
const admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();
exports.updateMaster = functions.firestore
.document('users/{uid}/figurines/{figurineId}')
.onUpdate(event => {
var newData = event.data.data();
var oldData = event.data.previous.data();
var updateData = {};
if (oldData.price != newData.price) {updateData.price = newData.price}
// Add any more changes that you may want to compare / update below...
// Then...
return db
.collection('master')
.doc(event.params.figurineId)
.update(updateData).then(response => {
console.log('We updated figurine', event.params.figurineId);
}).catch(err => {
console.error('There was an error', err);
});
});
I'm having a very simple setup with _User entity having a likes Relation with itself (reflective).
A common use case is list users.
I'm listing very few users (ex: 15), but i would also like to display the amount of likes he has.
Following standard suggested technique from Parse.com that would require a query for each of the 15 _User(s).
I don't think this is acceptable, maybe 2 queries are enough:
first one getting the first 15 _User(s)
second one getting the amount of likes each of the _User haves
But I have no idea if that's even possible with Parse API, so I'm asking for help ;)
If the column is a relation, then yes, getting the count will require a query per user.
If you expect the number of likes per user to be low (<100 is my semi-arbitrary rule of thumb), you could instead model likes as an array of pointers.
With that, you can know the count just by having the record in hand (i.e. someUser.get("likes").length). Even better, query include will eagerly fetch the related users...
userQuery.include("likes");
userQuery.find().then(function(users) {
if (users.length) {
var someUser = users[0];
var likes = someUser.get("likes");
if (likes.length) { // see, we can get the count without query
var firstLike = likes[0]; // we can even get those other users!
var firstLikeEmail = firstLike.get("email");
}
}
});
Otherwise, using relations, you're stuck with another query...
userQuery.find().then(function(users) {
if (users.length) {
var someUser = users[0];
var likes = someUser.get("likes");
return likes.query().count();
} else {
return 0;
}
}).then(function(count) {
console.log("the first user has " + count + " likes");
});
I'm quite new in MongoDB & MongooseJS. Actually learning the MEAN stack, I already love it.
I'm not sure to exactly understand noSQL principles, sorry If I duplicate.
I want to join 2 documents, type father and child, with 1 to N relationship.
Here's two solutions:
• Sub documents: http://mongoosejs.com/docs/subdocs.html
• References: http://mongoosejs.com/docs/populate.html
I've chosen the first one, simpler and IHMO closer to my problem.
Here's the code:
var personSchema = new Schema({
name : String
});
var groupSchema = new Schema({
name : String,
persons : [ personSchema ]
});
var Group = module.exports = mongoose.model('Group', groupSchema);
var Person = module.exports = mongoose.model('Person', personSchema);
Group.findById(groupId, function(err, group) {
var person = new Person();
person.name = "john";
group.persons.push(person);
group.save();
});
When I check for all groups, it work perfectly. The groups are returned, with the people saved.
Group.find(function(err, group) {
// group is full of groups & people
}
But when I check for person, nothing is returned.
Person.find(function(err, person) {
// person is empty
}
It seems that only the Group table document was filled. Is the solution implies to save 1/ the person and 2/ the group, and if so, will Person be saved in two different places (in Group document and in Person document)?
Group.findById(groupId, function(err, group) {
var person = new Person();
person.name = "john";
group.persons.push(person);
person.save(function(...) {
group.save();
});
});
Thanks
I am having following requirement:
1) To get list of all the users for whome profile has been changed.
2) Then query on FRUP (It is a custom object) to retrieve all the records which are associated with the user whose profile is changed.(FRUP object will contain the list of all the records created by all the users on all the objects say Account, Opportunity)
3) Update FRUP.
For achieving this I wrote one trigger through which i am able to fetch list of all the users whose profile has changed which is as follows:
Trigger UserProfileTrigger on User (before update) {
List<User> usr = new List<User>();
Map<String,String> userMap = new Map<String,String>();
for(User u: Trigger.new){
//Create an old and new map so that we can compare values
User oldOpp = Trigger.oldMap.get(u.ID);
User newOpp = Trigger.newMap.get(u.ID);
//Retrieve the old and new profile
string oldProfileId = oldOpp.profileId;
string newProfileId = newOpp.profileId;
//If the fields are different, the profile has changed
if(oldProfileId != newProfileId){
System.debug('Old:'+oldProfileId);
System.debug('New :'+newProfileId);
usr.add(u);
System.debug('User :'+usr);
}
}
}
Also Following are the fields on custom object FRUP:
1)Owner
2)Name
3)Record ID
4)Folder ID
5)Created By
6)Last Modified By
any help/suggestions??
I'm not sure what field on the FRUP references the user Id it relates to, but you can loop through the FRUP object with something like this:
List<FRUP> frupToUpdate = new List<FRUP>();
for (FRUP f : [
Select
OwnerId,
Name, //etc.
UserId //the field that references the user Id
from FRUP
where userId = : usr]) {
//update field on FRUP, e.g. f.Name = 'New Name';
frupToUpdate.add(f);
}
This selects the FRUP records that relate to the users with changed profiles. It then updates a field on the record and adds the record to a list for updating. Note that this should be after your loop for(User u: Trigger.new). Then update the FRUP records that have changed:
update frupToUpdate;
I have three collections that look like
User : user_hostname,user_mac_address,user_first_seen
Router : router_mac, router_ip, router_name
session : user_mac, router_mac, user_ip, user_duration( many different users and routers in different combinations)
So I want to create a new collection with all the information of these tables... i would like for it to be joined in such a way where for each session I can have the router info and user info attached to the session....there are currently over 3 million sessions in the session collection.
Map Function
router_map = function(){
var values = {
router_ip :this.router_ip
router_name: this.router_name};
emit(this.router_mac, values);};
session_map = function(){
var values = {
user_duration = this.user_duration
user_mac = this.user_mac
user_ip= this.user_ip};
emit(this.router_mac,values);};
Reduce Function
r=function(key,values){
var result = {};
values.forEach(function(value){
var field ;
for(field in value){
if (value.hasOwnProperty(field)){
result[field] = value [field];
}}});
return result;};
res=db.router.mapReduce(router_map,r,{out :{reduce :'routersession'}})
res=db.session.mapReduce(session_map,r,{out :{reduce :'routersession'}})
Result
db.routersession.find();
routersession : "_id"=*router mac* , values { "routerip" =data, "routername" = data, "user_duration"= data,"user_ip" = data,"usermac"=data}
I only get the first session linked with the router where i want all of the session under the router associated with it....when i put the other way it doesnt work... and i still want to join a third table to it.
I would also like to do queries like total number of unique session for each router.
I am new to mongodb and I am lost any help would be appreciated. Also let me know if you need any more info.