I have this system that takes in an array of SoundCloud user IDs, iterates them through a series of SC.get functions to obtain information of each user (user ID, username, followings and genre preference).
<script src="//connect.soundcloud.com/sdk.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<body>
<script>
//Initialize soundcloud API with client ID
SC.initialize({
client_id: "54cb0ff94ff9313ef6ca4674e9fe3026"
});
var userIds = [9110252, 55829847, 145189041, 4184647, 225458844, 22557004, 109447512];
var userids = [];
var usernames = [];
var userFollowingsE = [];
var profile =[];
var ready = 0
for(u = 0; u < userIds.length; u++){
var id = userIds[u];
getUserData(id);
function getUserData(userid){
//**************************** USER ***************************//
SC.get("/users/"+id, function(user){
userids.push(user.id);
usernames.push(user.username);
});
//********************** USER/FOLLOWINGS **********************//
SC.get('/users/'+id+'/followings',function(followings) {
var userFollowings = [];
for(i = 0; i < followings.collection.length; i++) {
userFollowings.push(followings.collection[i].username);
}
userFollowingsE.push(userFollowings);
ready++
if(ready >= userIds.length) onComplete();
});
}
}
function onComplete(){
console.log(usernames);
console.log(userIds);
console.log(userFollowingsE);
}
var users = [
{ userid: this.userids,
username: this.usernames,
genre: this.genres,
followings: this.followings,
}
]
</script>
</body>
What I want the system to do is associate these bits of information with their corresponding user in an object e.g.
var users = {
user9110252: {
userid = userid,
username = username,
genrePref = genre
followings = followings
}
}//etc...
However the arrays outputted from the system change order each time and I don't think are associated with one another.
I am unsure of how to do this and welcome any suggestions.
If you want the resulting array to look like you described, you should build the user Object as you go, instead of creating multiple arrays and then merging them.
Here is what I've tried, run it and see if it gives you the expected result. Also note that I did not include the genres, because I could not find them in the data provided.
//Initialize soundcloud API with client ID
SC.initialize({ client_id: "54cb0ff94ff9313ef6ca4674e9fe3026" });
var userIds = [9110252, 55829847, 145189041, 4184647, 225458844, 22557004, 109447512],
users = [];
for(var i=0; i<userIds.length; i++){ getUserData(userIds[i]); }
function getUserData(userid){
// The user Object you'll be building
var myUser = {};
// Grab the info for this user
SC.get("/users/"+userid, function(user){
myUser.userid = user.id;
myUser.username = user.username;
// Then get its followings
SC.get('/users/'+userid+'/followings',function(followings) {
myUser.followings = followings.collection.map(function(user){
return user.username;
});
// Push that user to the user list
users.push(myUser);
// Execute the callback if all users have been fetched
if(users.length == userIds.length){ onComplete(); }
});
});
}
function onComplete(){
console.log(users);
// Just for the demo:
document.body.innerHTML = '<pre>' + JSON.stringify(users,0,2) + '</pre>';
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://connect.soundcloud.com/sdk.js"></script>
Related
I am trying to find a way to find the value of the id given the email.
For example, If I had email2#gmail.com, It would give me the ID 108454568498950432898.
All emails are unique and there will be no repetition of emails.
This is my user tree:
Note: In the image it says email2 instead of email2#gmail.com. Ignore this
Here's my code so far:
(Code won't run obviously but it's easier to enter code using the embed)
var users;
var givenEmail = "email2#gmail.com";
var neededID;
var dataRef = firebase.database().ref('users');
dataRef.on('value', (snapshot) => {
const data = snapshot.val();
users = data;
});
var usersArray = Object.keys(users);
for(i = 0; i < usersArray.length; i++) {
if(users[i].email == givenEmail) {
neededID = i;
break;
}
}
I recommend using a query to perform the filtering on the server, instead of downloading the entire users node and filtering in your application code as you now do.
var givenEmail = "email2#gmail.com";
var dataRef = firebase.database().ref('users');
var query = dataRef.orderByChild('email').equalTo(givenEmail);
dataRef.once('value', (snapshot) => {
snapshot.forEach((userSnapshot) => {
console.log(userSnapshot.val().id);
});
});
Well, I think you are almost there.
users[i].email
you can retrieve the email using this method, and similarly you can do it with id too
users[i].id
Please note that you wanted to find email2#gmail.com but your firebase only have email2
Maybe you would want to change that
I have a Firebase web app serving as a registration system. When a user registers for a course, the course data is added to their list of all registrations as part of the callback function. When the user registers, the newest class is duplicated in the list. On a page load, each course is only listed once.
Realtime Database Structure
{
courses: {
courseIdA: {
// course data
},
couseIdB ... {}
},
users: {
uid: {
regs: {
courseIdA: true
}
}
}
}
When a user registers, they are added to both the course ID as a member object and to their users object under their uid. The callback fires twice because I'm writing to the courses ref and the users ref. Is there a way to write to both simultaneously? Or do I need to come up with a better structure for the database?
Get classes, listen for changes
PDReg.prototype.getAllClasses = function() {
this.database = firebase.database()
var uid = firebase.auth().currentUser.uid;
var courses = [];
var today = new Date().toISOString();
this.classesRef = this.database.ref('courses');
this.userRef = this.database.ref('users/' + uid + "/regs");
var setClass = function(snapshot) {
var course = snapshot.val();
course.key = snapshot.key;
// check for the current user in a course
if(course.members) {
if(course.members.hasOwnProperty(uid)) {
// This callback fires twice when someone registers
this.buildUserClasses(course);
} else {
this.buildAllClasses(course)
}
} else {
this.buildAllClasses(course)
}
}.bind(this);
// listen for changes to the classes database, rebuild the UI
this.classesRef.orderByChild('start').startAt(today).on('child_added', setClass);
this.classesRef.on('child_changed', setClass);
};
Register
PDReg.prototype.register = function(e) {
// It's a form submit, don't reload the page
e.preventDefault();
var form = this.courseForm;
var classes = [];
var uid = firebase.auth().currentUser.uid;
for (var i=0; i<form.elements.length; i++) {
// build the object to submit and add to an array
}
for (var i=0; i<classes.length; i++) {
this.coursesRef = this.database.ref('courses/' + classes[i].id + '/members/' + uid);
// Write the member object to `courses` under the correct key
this.coursesRef.set({'code': classes[i]['code']}).then(function(classes) {
// write to the user ref
firebase.database().ref('users/' + uid + '/regs/' + id).set(true);
onSuccess(title);
document.getElementById('allCourses').removeChild(document.getElementById(id))
}, function(e) {
onFailure(e, title);
});
}
};
I created a module that contains a mongoose model (user) that I want to export. For now, this only contains properties name and age.
var mongoose = require('mongoose');
var db = mongoose.createConnection('localhost', 'moviemeter');
var schema = mongoose.Schema({name:String, age: Number});
var User = db.model('user', schema);
module.exports = User;
Here, I would like to acces this model and find all the objects in it. Then, I would like to be able to fill my userArr variable with all the users in my database, but even though the first console.log returns the name of this object it doesn't push it into the array. What's the reason for this and what is a way I can fix this?
// user module
var User = require('./modelModules/memberModel');
var userArr = [];
var users = User.find({}, function (err, users) {
console.log(users[0].name)
users.forEach(function(user) {
userArr.push = user;
});
});
console.log(userArr[0].name)
It seems wrong usage of array push, you should use it as following:
userArr.push(user);
It is because you are using forEach, which is asynchon.
And your push has to be a function
userArr.push(yourUser)
Can you try with a "for" like this ?
// user module
var User = require('./modelModules/memberModel');
var userArr = [];
User.find({}, function (err, users) {
console.log(users[0].name)
users.forEach(function(user) {
for (var i = 0; i < users.length; i++) {
userArr.push(user);
}
console.log(userArr[0].name);
});
Hope it helps.
I am new to Mongo and Node. I am currently using Mongoskin and Bluebird to handle the db connection and queries (as suggested here: https://stackoverflow.com/a/23687958/2701348 ).
I have three collections: Users, Binders and Cards.
The Binders collection contains the information about Cards for each User.
Each document in Binders has as properties:
User Id <--- that refers to the User owning the Card
Card Code <--- that refers to a Card
Count <--- that refers to the number of cards owned by the User
I prefer to have a separate Cards collection so that when a Card changes, it changes for all the Users Binders.
Now I am willing to retrieve an array for a given user such as:
[{card: {card document}, count: 4}, ...]
I have the following problems:
the db connection should be closed after all the async db callbacks are called
the cards array should be returned after the last db.collection('cards').find gives back the results
I know my following code is wrong but can be a starting point for a discussion:
var getAllBinderCards = function(req, res){
var db = req.db;
var userId = req.userId;
var promiseBinders = db.collection('binders').find({userId: userId}).toArrayAsync();
promiseBinders.then(function(binderCards) {
if (binderCards) {
var promiseCards;
//console.log("------ binderCards: ", binderCards);
var cards = [];
for (var i = 0; i < binderCards.length; i++) {
var binderCard = binderCards[i];
promiseCards = db.collection('cards').find({Code: binderCard.Code}).toArrayAsync();
promiseCards.then(function(cardsDB){
if(cardsDB){
//console.log("Cards found: ",binderCard.Code, cardsDB);
for (var i = 0; i < cardsDB.length; i++) {
cardsDB[i].count = binderCard.count;
};
cards.concat(cardsDB);
}
});
}
promiseCards.then(function(){
db.close();
console.log("Binder Cards: " , cards);
res.json(cards);
});
}
});
}
I am struggling trying to figure out how to handle the promisfied asynchronous call correctly in order to send back the whole array and close the db connection.
I think I should try to build a promise before the for loop and use it to chain the query on Cards promises and lastly chain the db.close() and res.json(cards) statements.
[EDIT] Maybe the easiest solution is to simply use the $in filter inside a single db.collection('cards').find({Code: {$in: [bindersCodeArray] }}).toArrayAsync(); and avoid that for loop:
var getAllBinderCards = function(req, res){
var db = req.db;
var userId = req.userId;
var promiseBinders = db.collection('binders').find({userId: userId}).toArrayAsync();
promiseBinders.then(function(binderCards) {
if (binderCards) {
var binderCodes = binderCards.map(function(element){
return element.Code;
});
var promiseCards = db.collection('cards').find({Code: {$in: binderCodes} }).toArrayAsync();
promiseCards.then(function(cards){
var bindersDictionary = {};
for (var i = 0; i < binderCards.length; i++) {
bindersDictionary[binderCards[i].Code] = binderCards[i].count;
};
for (var i = 0; i < cards.length; i++) {
cards[i].count = bindersDictionary[cards[i].Code];
};
db.close();
console.log("Binder Cards: " , cards);
res.json(cards);
});
}
});
}
Still I am curious if there is an elegant way to solve this riddle using promises.
I would expect that using $in and array may have constraints on the number of binders you can pass and affect query performance. You can also try doing this with async#map. e.g.:
...
function(binders) {
async.map(binders, cardsForBinders, function(err, bindersWithCards) {
// TODO: close connection here.
}
function cardsForBinders(binder, callback) {
// 1. find cards for binder.
// 2. prepare transformed response: binderWithCards.
callback(null, binderWithCards);
}
}
...
Can anyone help me to get the user info from a person column using javascript? So far I have been able to read the list item and return a SP.FieldUserValue from which I can get a numeric Id (not sure what this ID is) and the display name. e.g.
var ManVal = oListItem.get_item("RecruitingManager").get_lookupValue();
var ManId = oListItem.get_item("RecruitingManager").get_lookupId();
How do I take this one step further to create a sp user object?
Ultimately what I'm trying to achieve is to retrieve the details from the list and then populate a people editor.
Ok, I've got it.
Here is my code, hope it helps somebody. I haven't included the method to retrieve the list item, just the line from that function where I'm getting the value of the person.
var _lineManager;
var lineManager = oListItem.get_item("RecruitingManager").get_lookupId();
_lineManager = oWebsite.getUserById(lineManager);
getLineManager();
function getLineManager() {
context.load(_lineManager);
context.executeQueryAsync(onGetUserNameSuccessLM, onGetUserNameFailLM);
}
function onGetUserNameSuccessLM() {
alert(lineManager.get_title());
var schema = {};
schema['PrincipalAccountType'] = 'User,DL,SecGroup,SPGroup';
schema['SearchPrincipalSource'] = 15;
schema['ResolvePrincipalSource'] = 15;
schema['AllowMultipleValues'] = false;
schema['MaximumEntitySuggestions'] = 50;
schema['Width'] = '280px';
var users = new Array(1);
var defaultUser = new Object();
defaultUser.AutoFillDisplayText = lineManager.get_title();
defaultUser.AutoFillKey = lineManager.get_loginName();
defaultUser.Description = lineManager.get_email();
defaultUser.DisplayText = lineManager.get_title();
defaultUser.EntityType = "User";
defaultUser.IsResolved = true;
defaultUser.Key = lineManager.get_loginName();
defaultUser.Resolved = true;
users[0] = defaultUser;
SPClientPeoplePicker_InitStandaloneControlWrapper('peoplePickerDivLinMan', users, schema);
}
function onGetUserNameFailLM(sender, args) {
alert('Failed to get user name. Error:' + args.get_message());
}
The person field (actually called "people picker") has a specific JavaScript function which you might find useful: GetAllUserInfo()
There is a nice article on MSDN:
How to: Use the client-side People Picker control in apps for SharePoint
The relevant code is:
// Get the people picker object from the page.
var peoplePicker = this.SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePickerDiv_TopSpan;
// Get information about all users.
var users = peoplePicker.GetAllUserInfo();
var userInfo = '';
for (var i = 0; i < users.length; i++) {
var user = users[i];
for (var userProperty in user) {
userInfo += userProperty + ': ' + user[userProperty] + '<br>';
}
}
$('#resolvedUsers').html(userInfo);
// Get user keys.
var keys = peoplePicker.GetAllUserKeys();
$('#userKeys').html(keys);
So basically you have to cast your field to a SPClientPeoplePicker and can then use GetAllUserInfo to iterate over all users in the field.