I'm making a realtime app with AngularJS and Firebase. I'm storing an array of data (players).
Below you can see a sample of my datastructure.
I can get all the players of this particular game, but how do I get for instance the player 'test'? The key is a generated value:
Game.find(gameId).child('/players/').push(player);
Then I thought, why don't I just 'update' '/players/'+name and set the name there. But unfortunatly I'm getting back objects inside an object:
{
players : {
"name":"...",
"test":"moretest"
}
}
I can access these properties but I cannot loop over them because it's not an array.
So basically what I want to do is "linq-wise" getting a player out of an array.
Game.find(gameId).child('/players/').where( name == ...);
Thanks in advance
Edit:
You are on the right track with storing just the name of the player instead of using push to generate an ID. You'll need to make sure your player names are unique though, otherwise you risk not being able to accommodate two players with the same name.
Every key in Firebase must have a value, so the best way to store a list of players where you want them to be accessible by the player name is to simply set them to a boolean value like 'true':
Game.find(gameId).child('/players').child(player).set(true);
Related
Let's say I have struct :
struct Planet {
var id : UUID
var name: String
...
}
I have an array of such structs which is constructed from data fetched from a database. I use this for a form in a browser where the user can:
edit the fields (eg change the name of Planet)
create one or more new Planets
at this time the user may not delete a Planet but it would be great if the solution would support that too
When the form is submitted I get an array with those structures (the order is also not the same as the original). What is the best/most efficient way to do update the data in the original array with the data from the second.
My current idea is:
map the original array to a dictionary with key= id, value= aPlanetStructure
loop over the second array (with the edited data) and if that 'key' can be retrieved in the dictionary (=data from first array)-> update the struct there, if not create an additional planet in the first array.
I'm not sure if this is a good approach, it seems like there could be a more efficient way (but I can't think of it). It would also not support deleting a Planet
In general, if you can separate out the elements of the array by action, you'll make your life easier.
For example:
var created= [Planet]()
var updated= [Planet]()
var deleted = [Planet]()
In your UI layer, when an edit is made, add the edited planet to the
updated array, when a planet is deleted, add it to the deleted array, etc.
Submit all 3 arrays with your form.
Loop over the results of each and pass too your create, update, and delete methods that access your database.
That will require restructuring your form code a bit, but... in general it's easier in your UI layer to tell whether someone is doing a create, an update, or a delete, than it is to mush them all together and try to figure it out after the fact by doing comparisons.
I've finally started to understand a lot of info regarding FireStore, but I'm wondering if I can get some assistance.
If I had a setup similar to or like this:
races
Android
name: Android
size: medium
stats <---- this is the map
str: 10
sex: 12.... (more values)
How would I parse this? I am looking to make specific TextViews apply values found in the database so that I can simply update the database and my app will populate those values so that hard coding and code updating won't be nearly as troublesome in the future.
I currently use something like this:
val androidRef = db.collection("races").document("Android")
androidRef.get().addOnSuccessListener { document ->
if (document != null) {
oneOfTheTextViews.text = document.getString("str")
} else {
}
The issue is currently I can only seem to access from collection (races) / document (android) / then a single field (I have "str" set as a single field, not part of a map or array)
What would the best practice be to do this? Should I not nest them at all? And if I can reference said nesting/mapping/array, what functions need to be called? (To be clear, I am not asking only whether or not it is possible - the reference guides and documents allude to such - but what property/class/method/etc needs to be called in order to access only one of those values or point to one of those values?).
Second question: Is there a way to get a list of document names? If I have several races, and simply want to make a spinner or recycler view based on document names as part of a collection, can I read that to the app?
What would the best practice be to do this?
If you want to get the value of your str property which is nested within your stats map, please change the following line of code:
oneOfTheTextViews.text = document.getString("str")
to
oneOfTheTextViews.text = document.getString("stats.str")
If your str property is a number and not a String, then instead of the above line of code please use this one:
oneOfTheTextViews.text = document.getLong("stats.str")
Should I not nest them at all?
No, you can nest as many properties as you want within a Map.
Is there a way to get a list of document names?
Yes, simply iterate the collection and get the document ids using getId() function.
I'm using React Native and Open Weather Map API to build a small weather app. The data I retrieve from the API call is more than I want to use so I parse out just the pieces I need and store them in an array. I then take the array and set it to a state object. I can reference the object, but instead of saying my array is an array, it says it's an object, and thus won't let me use any array methods on it. How do I get around this?
//reponseData is the data retrieved from the API call; the data retrieved is an object with arrays and objects
within. The forecast data for the next five days is given in 3 hour increments, so you have a 40 item array of
data pieces. I loop through this list of 40 items, pull out just what I need...
let forecastArray = [];
for (let i=0; i<responseData.list.length; i++) {
let day = responseData.list[i].date
let high = responseData.list[i].weather[0].hiTemp
let low = responseData.list[i].weather[0].loTemp
let condition = responseData.list[i].sys.condition
forecastArray.push(day)
forecastArray.push(high)
forecastArray.push(low)
forecastArray.push(condition)
this.setState({
forecastData: forecastArray
})
When I log, I get an array....
console.warn("forecast is: ", this.state.forecastData)
OUTPUTS: forecast is: ["11-06-2019", 52.5, 47.3, "sunny", "11-06-2019", 63.9, 39.7, "sunny", ...]
Referencing this.state.forecastData[2], for example, however was giving me errors. So I checked the typeof this.state.forecast to see why and it says the array is an Object? I need to further divide out the array data and manipulate it. The first several items (e.x. forecastData[0] through forecastData[9] would be for the forecasted weather for 11-06-2019 at 3pm, ,6pm, 9pm so I need to pull those items, get the highest high and lowest low, etc. I can't do that since I can't even reference the items in the array.
Things I've tried:
using Object.entries and Object.assign methods, but that just splits the items into several arrays, with the first item being the location number and the second item being the array item content. I've tried manipulating the array within the component that uses it, but it still is an Object not an Array, so I can't reference the individual items. The data set is large enough I don't think it would be best practice to push each of the 40+ items into their own state object key.
in Javascript array is a subset of object , i'e it has the same prototype. So typeof Array will be an object. Thats not an issue. Can you update with the error which you are getting while accessing this.state.forecastData[2] coz what i . believe its something not with syntax , rather with the duration of API call.
I would recommend when accessing this.state.forecastData[2] first check if its length is greater than 0 , that way you are sure that there is data inside the array.
constructor(props){
forecastData:[]
}
and when you use it ,
if(this.state.forecastData.length > 0){
this.state.forecastData[2]
}
Try this, and revert with doubts.
Thank you, Gaurav Roy! You were partly correct. The typeof didn't matter at all. But the issue wasn't with the duration of my API, it was that my component was trying to render when it didn't have the data from the API call yet! I put in a conditional
{this.state.forecast !== null && <Forecast forecast=this.state.forecastData />}
and got things working now. Thanks for the quick reply!
I'm new to Firebase and have a function that writes all of my event ID's to an array. I want to use the last value in that array (the last event ID) to lookup the children of that specific eventID.
I know how to get the last item in the array but how do I put that into my .child() path?
I tried the code below, but it doesn't seem to work. I'm guessing that because .child("(lastEvent)") isn't a valid path.
let lastEvent = eventIDArray.last
refHandle = ref.child("Bouts").child("\(lastEvent)")
How do I plug the lastEvent value in as my path? Or is that even possible? Again, total newbie- alternatives welcome.
Sorting and filtering data
you can use sorting and filtering function to get the item.
To get the last item you can write the query like this.**
let recentBoutsQuery = (ref?.child("Bouts").queryLimited(toLast: 1))!
This will return 1 entry from last of your database which the last entry.
You can learn more from the firebase documentation. Work with Lists of Data
I am a beginner.
trying to make a simple soccer game.
All values are initialized to 0.
select 2 different teams from the dropdown >> enter final score (cannot be negative).
On clicking 'Final score' button,
function should increment the value of 'Played' to 1 for both the teams.
as well as display in the table.
function updateTeam(winner,looser){
if (var a = $scope.Ligateams.lastIndexOf(winner)){
$scope.Ligateams.played = "1";
}
}
Code here
I took a look here, found a few things. I did not change everything, but you should have the tools to make other changes (ex. updating the draw count).
You had two controllers, one was basically acting just to retrieve the list of teams. This complicated the manipulation of the data, so I changed to use $http, and loaded from a .json file.
In your UI, you iterated over the teams, and stored the name. I changed this to store the index for the two teams that were selected. This is used throughout the code to access that team. Since iteration was already occurring in the UI, it made sense to store those indices vs. searching it again in the controller. This grants us access to the object in the teams array with which to increment values.
Relevant bits of code follow.
Load Data via HTTP
$http.get('teams.json').then(function(resp){
$scope.Ligateams = resp.data;
})
Using the index vs. Name
<select ng-model="Matchteam2.idx" ng-disabled="editButton1">
<option ng-repeat="Matchteam2 in Ligateams"
value={{$index}}>{{Matchteam2.name}}
</option>
</select>
Accessing Team info in the Controller
Now we can get the team object from the array of teams with the index.
var team1 = $scope.Ligateams[$scope.Matchteam1.idx];
var team2 = $scope.Ligateams[$scope.Matchteam2.idx];
team1.played++;
team2.played++;
Accessing Team info in the UI
Since the basic 'name' field is no longer on Matchteam#, we can access the name property on the team object in the Ligateams array, again using the index.
Goal by Team <b>{{Ligateams[Matchteam1.idx].name}}</b
Here's a sample with some things fixed: https://plnkr.co/edit/Yby8D0z8IIEGXNxlwX4D?p=preview.