cross-referencing two firebase arrays to obtain data - javascript

I was wondering if there's an easy way to pull out a value from one array based on its corresponding name.
Here, I've obtained the user email from the "coupons" collection. Now I would like to search through the "users" collection, find similar email, and output its corresponding "Name" ("Wes Haque Enterprises") to a $scope variable.
I already have references to both collections and $scope objects which have those references stored.
I just wanted to know if there's an easy way to traverse through the $scope.users object looking for the string "wes#wes.com" and then extracting "Wes Haque Enterprises" from it. Thanks.

Assuming that you don't really want to iterate (traverse?) over a bunch of arrays but instead query for the data you need...
You can query the users node for the data you need. In MacOS:
FQuery *allUsers = [usersRef queryOrderedByChild:#"emailAddress"];
FQuery *thisUser = [allUsers queryEqualToValue:#"wes#wes.com"];
[thisUser observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
for ( FDataSnapshot *child in snapshot.children) {
NSLog(#"%#", child);
}
}]
The result of the query will contain "Wes Haque Enterprises"
Or
ref.orderByChild("emailAddress").equalTo("wes#wes.com").on("child_added", function(snapshot) {
console.log(snapshot.key());
});

Related

Autocomplete values using array

Is it possible to use two arrays to insert data into values rather then hard coding the names of the users in tabulator.
One array would hold the username while the other would hold the actual name of the user.
{title:"Approver", field:"Approver", editor:"autocomplete", editorParams:
{
values:{
"jd1":"John Doe",
"mm12":"Marty McFly",
}
}
}
You should use Object.keys(values) and Object.values(values) to obtain username and fullname as two arrays, respectively.

how to access key/value pairs from json() object?

I'm calling an external service and I get the returned domain object like this:
var domainObject = responseObject.json();
This converts the response object into a js object. I can then easily access a property on this object like this
var users = domainObject.Users
Users is a collection of key/value pairs like this:
1: "Bob Smith"
2: "Jane Doe"
3: "Bill Jones"
But CDT shows users as Object type and users[0] returns undefined. So how can I get a handle to the first item in the collection? I'm assuming that some type of type cast is needed but not sure how I should go about doing this
UPDATE
Here is one way I could access the values:
//get first user key
Object.keys(responseObject.json().Users)[0]
//get first user value
Object.values(responseObject.json().Users)[0]
But I need to databind through ng2 so I was hoping for a simpler way like this:
<div>
<div *ngFor="let user of users">
User Name: {{user.value}}
<br>
</div>
</div>
Maybe I should just create a conversion function in my ng2 component which converts the object into what I need before setting the databinding variable?
UPDATED ANSWER
So after scouring through a few docs I found the "newish" Object.entries() javascript function. You can read about it here. Pretty cool.
Anyways, give this a try. I am ashamed to say that I don't have time to test it, but it should get you going in the right direction.
usersArray = []
// Turn Users object into array of [key, value] sub arrays.
userPairs = Object.entries(users);
// Add the users back into an array in the original order.
for (i=0; i < userPairs; i++) {
usersArray.push(_.find(userPairs, function(userPair) { return userPair[0] == i }))
}
ORIGINAL ANSWER
I would use either underscore.js or lodash to do this. Both are super helpful libraries in terms of dealing with data structures and keeping code to a minimum. I would personally use the _.values function in lodash. Read more about it here.. Then you could use users[0] to retrieve the first item.
The only caveat to this is that lodash doesn't guarantee the iteration sequence will be the same as it is when the object is passed in.
users = _.values(users);
console.log(users[0]);
How about this:
let user= this.users.find(() => true)
This should return the "first" one.
If your initial object is just a plain object, how do you know it is sorted. Property members are not sorted, ie: looping order is nor guaranteed. I´d extract the user names into an array and the sort that array by the second word. This should work (as long as surnames are the second word, and only single spaces are used as separators).
var l=[];
for(var x in users) {
push.l(users[x]);
}
var l1=l.sort ( (a,b) => return a.split(" ")[1]<b.split(" ")[1]);

Passing data between two collections - Meteor JS

Example
I have two collections, one for Posts and one for Labels that look like this:
Post {
"_id": "WZTEGgknysdfXcQBi",
"title": "ASD",
"labels": {},
"author": "TMviRL8otm3ZsddSt",
"createdAt": "2016-01-14T08:42:42.343Z",
"date": "2016-01-14T08:42:42.343Z"
}
Label {
"_id": "9NCNPGH8F5MWNzjkA",
"color": "#333",
"name": "Grey Label",
"author": "TMviRL8otm3ZsddSt"
}
What I want to achieve is to have Posts with multiple Labels.
Problem is I cannot insert label data into the post.
I have a template to add new post and in there I am repeating over the labels. Then in the helpers I check which label is checked and store it into an array, but I cannot insert that array in the Posts collection.
'submit .add-entry': function(event) {
var title = event.target.title.value;
var description = event.target.description.value;
var checkedLabels = $('.label-checkbox:checked');
//initiate empty array
var labelsArray = [];
//go over the checked labels
for(i = 0; i < checkedLabels.length; i++){
var label = checkedLabels[i].value;
// store ids into array
labelsArray.push(label)
};
Posts.insert({
title: title,
description: description,
labels: labelsArray
});
Q1: Should I insert all the tags data or only the ID fetch more details from the Tags collection based on that ID?
Q2: How can I insert that array of labels into a Post? The code above does not work because it needs an Object
Q3 What is the best way to achieve such relationship between collections?
(Q1) You can insert all tag IDs to that labels list and keep that updated (Q3) I think that's a good practice; in your development process try to publish using composite collections with this package: https://github.com/englue/meteor-publish-composite
(Q2) Inserting is easy:
Post.insert({title:'Abc', labels:['one', 'two']});
You would need to use $addToSet to update. Here's an example of a possible method:
let setModifier = {
$addToSet: {
labels: myArrayOfLabelIDs
}
};
return Post.update({
_id: id
}, setModifier);
Note: Never use inserts on the client (like you did). My example can be added as a method on the server (use check() inside that) and can be called from the client upon submit like:
Meteor.call('myMethod', id, labelsArray)
Q1: Should I insert all the tags data or only the ID fetch more
details from the Tags collection based on that ID?
It depends: does the label change? If it mutable, then storing the ID only is best so that fetching the Label by ID will always return the proper data. Otherwise you need to update every Post with the new label info.
Q2: How can I insert that array of labels into a Post? The code above
does not work because it needs an Object
If the code does not work, it is likely that you are using some sort of schema that is not matched: to insert an array in place of an object, you need to modify the schema to accept an Array. You did not post details of a schema.
Q3 What is the best way to achieve such relationship between
collections?
You should look at 'denormalization': this is the term used for this type of things in a NoSQL database like MongoDB.
There is no straight answer, it depends on the relationship (1-1, 1-many, many-1) and the ratio of each 'many': in some cases it is best to nest data into objects if they are immutable or if dealing with updates is not too much of a pain.
this series of blog posts should help you get a better understanding:
http://blog.mongodb.org/post/87200945828/6-rules-of-thumb-for-mongodb-schema-design-part-1

extracting a list of 2 property values

I have an object array:
user :[
{
name: String,
username: String
}
]
I want to view every change either to name or username.
I found underscore _.pluck only does the trick for one property (_.pluck(user, 'name')
Is there another way to have the list of both values?
With pluck you can only use one property, it simply isn't made to retrieve multiple. The method you would want to use is map, as suggested in this relevant question + answer: How to pluck multiple attributes from a Backbone collection?
Assuming you want the following output [['nameA','usernameA'],['nameB','usernameB'],...]], you could use map in the following manner:
var myResult = users.map(function(user) {
return [user.name, user.username];
});
NOTE: I changed the variable user to users to make more sense with your data.

How to find items in an array that are not contained in a MongoDB collection

Say I have an array of city names, and a MongoDB collection of city names. Say that my array looks like:
["San Francisco", "chicago", "New York", "Los Angeles"]
And my collection looks like
{{cityName: "chicago"}
{cityName: "New York"}}
What I'd like to do is perform a query that returns to me San Francisco and Los Angeles. So far, my only idea is to just perform the query, get the matches, and do an array subtraction from the original array (and thus get my cities), but I wonder if theres a way to do it in a one step query.
Thanks in advance!
You need to perform the following query against your MongoDB collection:
db.cities.distinct("cityName", {cityName:{$in:["new york","los angeles","chicago","san francisco"]}})
This will return the array of cities that matched something in the collection. In your example above you would get back:
["chicago","new york"]
You can now subtract those elements from original array and get the desired result.
The key is to do a distinct query (rather than getting all the results) and pass a query limiting the query to the cities you care about, not all cities that are represented by your collection.
The array subtraction is the only way to go ahead with this as even if you use any mongodb driver and if it supports this function, it will eventually be doing the same thing.
A query on MongoDb will always return the values which are either contained in it or a null value. So you have to take the values and do an array subtraction.
Is there a coma in your collection ?
{{cityName: "chicago"},
{cityName: "New York"}}
If yes, you can do:
for( var i in collec ){
var cityname = collec[i]['cityname'];
// if you use jquery
var getcity = $.grep( yourarray, function(n,i){
return n == cityname;
});
// getcity in an array with all matching elements
console.log(getcity);
}

Categories

Resources