Observable contains array of ID to call another observable - firebase

I have a data structure in firebase
{
"name": "Sample",
"category": ["123456", "789012"]
}
The array of category contains ID which refers to documents in another collection. I can get the above document as Observable. What I really what as the end result is the below data structure
{
"name": "Sample"
"category": [
{
"name": "Category 1"
},
{
"name": "Category 2"
}
]
}
How can I bring this data? I don't think switchMap works for this. If so, can someone give an example of that?

You can try using flatMap and forkJoin. FlatMap allows you to chain multiple async requests together and forkJoin allows you to wait for all observables to return a value before continuing.
And you could wright something like this:
var finalData;
firstRequest('sample').flatMap((data) => {
// assuming data = { name: "Sample", catagory: [ "23123", "31321", ... ] }
finalData = data;
var observables = [];
data.catagory.forEach((c) => {
observable.push(secondRequest(c));
});
return forkJoin(observables);
}).flatMap((results) => {
// assuming results is an array like [ { name: "Catagory 1", ... } ]
finalData.category = results;
return finalData;
});

Related

How to add elements to a svelte writable store vector

I have this store:
export const flights = writable<APIResponse>([])
And I want to add elements at the end of that array. I tried his:
flights.set({ ...flights, input })
But that doesn't add, it overwrites the existing elements, leaving only the one in input. How can I do that?
I am in a .ts. I'm taking over someone else's job who left the company and I'm new to all of this, I still don't have a clear idea of this mix of languages/frameworks.
When I print flights appears empty.
console.warn(flights store: + JSON.stringify(flights))
{}
Some advances. It seems it was not empty. I wasn't printing it the correct way. I can see the elements added if I add them like this:
unconfirmed_flights.update((data) => {
data.push(input))
return data
})
and print the content like this:
unconfirmed_flights .update((data) => {
console.warn(JSON.stringify(data))
return data
})
That prints something like: [{json_object}, {json_object}].
The thing is that in fact I have two stores:
export const flights = writable<APIResponse>([])
export const unconfirmed_flights = writable<APIResponse>([])
The code receives several items that are added to unconfirmed_flights correctly. Then a dialog opens and if the user presses accept I need to copy the items in unconfirmed_flights to flights. I do that like this. First I create an index (id) with the empty array:
flights.update((data) => {
data[id] = []
return data
})
Then I add all the elements in unconfirmed_flights:
unconfirmed_flights.update((uplan) => {
flights.update((data) => {
data[id].push(uplan)
return data
})
return uplan
})
But the result, instead of
{"id": [{json_object}, {json_object}]}
is
{"id": [[{json_object}, {json_object}]]}
With that nested array. However, if I don't do the step of data[id] = [], I get a "Uncaught (in promise) TypeError: data.push is not a function", that I read is because the index does not exist. How can I avoid that nested array?
const flights = writable([])
If you want to add a value to a store from a .js file use .update() where the current value is available
flights.update(value => [...value, newValue])
Inside a .svelte file the store variable can be prefixed with $ to access the value and the new value could be added like this
$flights = [...$flights, newValue]
After three days of unsuccessful attemps to add the content exactly as I needed, I found the help of a JS expert. There it goes the solution.
Having
flights = {"1": { "name": "name1" } }
and
unconfirmed_flights = [ {"2": { "name": "name2" } }, {"3": { "name": "name3" } } ]
The goal was to add the unconfirmed_flights to flights:
flights = {"1": { "name": "name1" },
"2": { "name": "name2" },
"3": { "name": "name3" } }
And that was done like this:
flights.update((plan) => {
const uplan = get(unconfirmed_flights)
uplan.forEach((uplanItem) => {
plan = { ...plan, ...uplanItem }
})
return plan
})
being
export type APIResponse = { [key: string]: any }
export const flights = writable<APIResponse>([])
export const unconfirmed_flights = writable<APIResponse[]>([])

What is the way to update or insert a record on Firebase with Flutter?

I have a collection users like this:
[{
'uid' : '1',
'favourites' : [
{ // fav1 },
{ // fav2 },
{ // fav3 },
etc
]
},
{
'uid' : '2',
'favourites' : [
{ // fav1 },
{ // fav2 },
{ // fav3 },
etc
]
},
etc
]
In some situations I have to update the favourites collection with a new "fav" and I can do that in this way:
final doc = FirebaseFirestore.instance.collection('users').doc(userId);
doc.update({ 'favourites': FieldValue.arrayUnion([fav.toJson()]) });
however the item might be not there so I have to use doc.set to create a new item. As I am new with Firebase, what is a "best practice" for a problem like this (if the element is not there create it first, otherwise update it)?
You can specify a merge option to set, which does precisely what you want:
doc.set({ 'favourites': FieldValue.arrayUnion([fav.toJson()]) }, SetOptions(merge : true))
You can use a function that can check if there is a doc or not with that specific info. And you can create a if-else statement depends on if there is a doc named like that or not.
An example function for checking the doc:
Future<bool> checkIfDocExists(String stuffID) async {
try {
/// Check If Document Exists
// Get reference to Firestore collection
var collectionRef = FirebaseFirestore.instance
.collection('favorites');
var doc = await collectionRef.doc(userId).get();
return doc.exists;
} catch (e) {
throw e;
}
}

ASP.Net Core - Get All data of a post form

I want to save all data of a form.
My form has these elements-
( Using Postman Plugin )
My controller is like this-
[HttpPost]
public async Task<IActionResult> Insert(IFormCollection data)
{
return Ok(data);
}
So, I am getting something like this-
[
{
"key": "user_id",
"value": [
"'12'"
]
},
{
"key": "title",
"value": [
"123"
]
},
{
"key": "text[]",
"value": [
"werwer",
"ghj"
]
}
]
I want to get the value of texts.
So, for this case-
"werwer",
"ghj"
So, I have tried something like this-
foreach (string description in data["text"])
{
// description => empty
}
and also tried this-
data.text
and also-
data->text
But nothing works for me.
Can anyone please help?
Thanks in advance for helping.
Why not loop through each keys and if the key is "text", get the values. Since the value is a comma seperated string, you can call the Split method on that to get an array which contains 2 items( from your sample input).
foreach (string description in data.Keys)
{
if (description.Equals("text"))
{
var v = data[description];
var stringItems = v.Split(',');
foreach (var stringItem in stringItems)
{
//do something with stringItem
}
}
}
BTW, the key should be text, not text[]. Even if you have muliple input fields with the same name "text", when you submit, It will be a single key ("text") with 2 items int he value property
{
"key": "text",
"value": [
"werwer",
"ghj"
]
}

How can I get records from Firebase where a certain field is empty

I'm building an app where I need to process 5k+ tasks in small batches. For that I have a queue of tasks that is stored in a Firebase. I'd like to be able to pull certain amount of tasks with empty status, update their status and write back.
Currently I don't see how I can pull data where a certain field is empty. Is it possible? If not, what would be the alternative solution?
UPDATED 02/12. Here is the data structure that I have:
{
"-KAMnc89C5Yi_ef18ewc" : {
"0": {
"url": "https://excample.com/url",
"status": "done"
},
"1": {
"url": "https://excample.com/url1"
},
"2": {
"url": "https://excample.com/ur2"
},
"3": {
"url": "https://excample.com/ur3"
}
}
And this is the query I'm using:
queueRef.orderByChild('status').equalTo(null).limitToFirst(1).once('value', function(snapshot) {
console.log(snapshot.val());
});
queueRef points to "-KAMnc89C5Yi_ef18ewc" from the data above.
I expect to get one object - "1", but instead I'm getting all of them. Is there something I'm missing?
Firebase doesn't allow you to store a property without a value. That simply means that the property doesn't exist.
Luckily this doesn't really matter too much, because this seems to work. Given this data structure:
{
"-KADbswYg3FiQF78mmUf": {
"name": "task1",
"status": "done"
},
"-KADbugr7QzTx0s93Fs0": {
"name": "task2"
},
"-KADbvKvBgiAXxnQvoBp": {
"name": "task3"
}
}
This works:
ref.orderByChild('status').equalTo(null).once('value', function(snapshot) {
console.log(snapshot.val());
})
This prints task2 and task3.
Use the DataSnapshot.exists()
This will returns true if this snapshot contains any data. If not it will return false. According to the documentation here. It is slightly more efficient than using snapshot.val() !== null.
With a data structure like this:
{
"girlfriend": {
"first": "Pamala",
"last": "Anderson"
}
}
And a firebase call like this:
var ref = new Firebase("https://myURL/girlfriend/Pamala");
ref.once("value", function(snapshot) {
var a = snapshot.exists();
// a === true
var b = snapshot.child("girlfriend").exists();
// b === true
var c = snapshot.child("girlfriend/first").exists();
// c === true
var d = snapshot.child("girlfriend/middle").exists();
// d === false (because there is no "name/middle" girlfriend in the data snapshot)
});

All instances of a node by xxxx name

Is there a one liner or how can I get all instances of a named list in any node?
say I get jason where multiple nodes could have a sub collection called "comments". How can I get all nodes that contain a collection of "comments"?
Thanks,
If you can provide an example of the JSON, I can give you a definitive answer.
However, I can post some of the JSON I'm parsing and you can see how it works and possibly shape it to fit your needs.
"abridged_cast": [
{
"name": "Clark Gable",
"characters": ["Rhett Butler"]
},
{
"name": "Vivien Leigh",
"characters": ["Scarlett O'Hara"]
},
{
"name": "Leslie Howard",
"characters": ["Ashley Wilkes"]
},
{
"name": "Olivia de Havilland",
"characters": ["Melanie Hamilton"]
},
{
"name": "Hattie McDaniel",
"characters": ["Mammy"]
}
],
Notice how abridged_cast is an array of values, and one value in that array (characters) is an array itself.
Here's how I fetch the data:
var castMembers = (JArray) x["abridged_cast"];
foreach (var castMember in castMembers)
{
CastMember member = new CastMember();
member.Actor = (string) castMember["name"];
var characters = (JArray) castMember["characters"];
foreach (var character in characters)
{
member.Characters.Add((string)character);
movie.Cast.Add(member);
}
}

Resources