.remove() is not working on my specific reference - javascript

This is my database:
And I want to delete the "small_green" value, so I'm trying with this:
const refToDelete = firebase.database().ref().child('products').orderByChild('fruits').equalTo('small_green');
refToDelete.remove();
But it throws this error:
I'm following this tutorial and this documentation.
What I'm doing wrong?

You can only call remove() on a DatabaseReference, which is a reference to an exact location in the database.
Your firebase.database().ref().child('products').orderByChild('fruits').equalTo('small_green') is a query, which is not a exact location. That means you can't call remove() on it. You will first have to execute the query to get the matching locations, and then call remove() on each of those.
Typically this will be something along the lines of:
const query = firebase.database().ref().child('products').orderByChild('fruits').equalTo('small_green');
query.once('value', functions(snapshot) {
snapshot.forEach(function(childSnapshot) {
childSnapshot.ref.remove();
});
})
Aside from that you're ordering on the wrong child node (as you said in the comments). So you'll want:
const query = firebase.database().ref().child('products/fruits').orderByChild('attrs').equalTo('small_green');

Related

Firestore DocumentSnapshot.data() returns undefined, but in the console it definetly has and it works for other documents

In this Firebase Function I'm getting two DocumentSnapshots, the first works fine, I can get the data (emailNonce) from the db, but the second DocumentSnapshot somehow has no data, the object is there, I can see it in the logs, but calling .data() on it returns undefined:
const addRentalFct = async (data, context) => {
// this works:
const secretsRef = db.collection('user-secrets').doc('Yv3gZU8TeJTixl0njm7kUXXpvhc2');
const secretsSnap = await secretsRef.get();
const dbNonce = secretsSnap.data().emailNonce;
functions.logger.log('got the dbNonce: ', dbNonce);
// this doesn't work, but ir's the same logic as above:
const boxesSecretsRef = db.collection('box-secrets').doc('CB8lNQ8ZUnv4FDT6ZXGW');
const boxSecretsSnap = await boxesSecretsRef.get();
functions.logger.log('got the boxSecretsSnap: ', boxSecretsSnap);
functions.logger.log('got the boxSecretsSnap.data(): ', boxSecretsSnap.data());
const boxPassword = boxSecretsSnap.data().password;
functions.logger.log('the box secret is: ', boxPassword);
...
}
The DB:
box-secrets collection
user-secrets:
(the secrets are from my dev environment)
The problem was that I copied the id for the new document from an already existing document in the console like this:
Automatically there was a space added in front. When I created the new doc, the space was not visible, but I could create another doc with the same id, without the space in front. Here you see that it
s not that obvious, it looks like there are two docs with the exact same id:
When having it like this, the firebase function didn't find any of the two docs. I had delete both and readd it without space, then it worked.

Using Event Target to return specific data in the console

I'm trying to use an event listener to return specific data from the console made from an API call and apply it to a variable to make another API call.
The calls are made through functions that return the data in JSON format.
The console data is as follows:
href: "https://api.spotify.com/v1/tracks/7f0vVL3xi4i78Rv5Ptn2s1"
id: "7f0vVL3xi4i78Rv5Ptn2s1"
I'm trying to only access the id portion to use it in a new API call. I have an event listener that I would like to use which receives the id on click.
DOMInputs.tracks.addEventListener('click', async (e) => {
const trackId = e.target.id;
}
However, the variable trackId contains the href instead of the id. Resulting in:
app.js:74 GET https://api.spotify.com/v1/audio-analysis/https://api.spotify.com/v1/tracks/7f0vVL3xi4i78Rv5Ptn2s1 404
Where the second link is contained in ${trackId} Is there a work around or am I missing something?
For those wanting to know the same thing. I simply used const trackEndPoint = e.target.id.replace('https://api.spotify.com/v1/tracks/', '');

Creating a paginated chronological query in Firestore

Hopefully a relatively simple question here with using Firestore querys
I am trying to create essentially a news feed, sorting the newest content from the oldest content. That part is pretty easy, I use:
var first = db.collection("feeds/0/active").orderBy("timestamp", "desc").limit(3);
Which retrieves the 3 newest entries in the news feed. My then idea is in the next query, to pull down the next 3 items in the feed. So if we are going by age, 4,5,6 in the collection in terms of how new the items are.
To do this I grab the last item in query one, and use that node's timestamp as my start at value in query 2:
var first = db.collection("feeds/0/active").orderBy("timestamp", "desc").limit(3);
first.get().then(function (documentSnapshots) {
// Get the last visible document
var lastVisible = documentSnapshots.docs[documentSnapshots.docs.length-1];
var next = db.collection("feeds/0/active").orderBy("timestamp", "desc").startAt(lastVisible.data().timestamp).limit(3);
next.get().then(function(docSn){
console.log("SECOND QUERY!")
docSn.forEach(function(doc) {
console.log(doc.data().message)
})
})
The Result of this code returns the same as the first query returns, the nodes 1, 2, 3 despite trying to tell the second query to start at node3
I also tried passing in a javascript object instead:
var datevalue = Date.parse(lastVisible.data().timestamp)
var next = db.collection("feeds/0/active").orderBy("timestamp", "desc").startAt(datevalue).limit(3);
Which also unfortunately did not work.
I also tried passing in the entire snapshot item, and got the error
"Malforormed Calls from JS: field sizes are different.
[[9,38,38,38],[0,0,1,0],
etc.."
Not really clue where to start with this as I have read through the docs and any examples and I could find and can't seem to figure it out. The only other way I can think of implementing this is by using a Cloud Function to number each node upon creation.. but that feels hacky
Any help would be huge! Thanks
I have a collection called "books" with a field called "created" of type Timestamp. This is not a string. This is not a Date. Please see the Timestamp docs. You need to specify in your settings that you want to use the new Timestamp type instead of Date for your timestamp fields. (See docs for firestore settings)
Example of initiating your firestore and set the TimestampsInSnapshots setting:
var firebaseApp = firebase.initializeApp({
apiKey: [APIKEY],
authDomain: [FIREBASEAPPDOMAIN],
projectId: [PROJECTID]
});
var firestore = firebase.firestore();
var settings = { timestampsInSnapshots: true }; // force Timestamp object instead of Date
firestore.settings(settings);
When this is done, i've run the below code and I get the expected results. First query returns three results. Newest first, latest last.
The second query returns the next three items.
var first = db.collection('books').orderBy("created", "desc").limit(3);
console.log("FIRST QUERY!")
first.get().then(function(documentSnapshots) {
documentSnapshots.forEach(function (doc) {
console.log(doc.data().created.toMillis())
});
// Get the last visible document
var lastVisible = documentSnapshots.docs[documentSnapshots.docs.length - 1];
var next = db.collection('books').orderBy("created", "desc")
.startAfter(lastVisible.data().created).limit(3);
next.get().then(function (docSn) {
console.log("SECOND QUERY!")
docSn.forEach(function (doc) {
console.log(doc.data().created.toMillis())
});
});
});
The console from the above code:
FIRST QUERY!
1540573716371
1540573676652
1540573668643
SECOND QUERY!
1540573658893
1540573536420
1540536647891
Are you checking the entire list returned? Or, just the first node?
If you use startAt, then the first node in the second list will be the last node in the first list (docs). I suggest using startAfter (docs).
Example:
var db = firebase.firestore()
var query = db.collection('feeds/0/active').orderBy('timestamp', 'desc').limit(3)
query.get().then((firstSnapshot) => {
var first3 = snapshot.docs
query.startAfter(first3[2]).get().then((nextSnapshot) => {
var next3 = snapshot.docs
})
})

Exact syntax to find and modify (or delete) a matching node in Firebase with JavaScript

I need to loop over my firebase and find a specific record within /users/{currentUser}/things/ where thing.feature === "something", then modify or delete that node. What is the exact syntax to do that?
I've looked at the docs but find a mix of unhelpful statements like
When using orderByValue(), children will be ordered by their value.
or that the Return Value for equalTo() is
The generated Query.
One of the later examples in the Firebase documentation on querying gives an example of this.
var ref = new Firebase("https://dinosaur-facts.firebaseio.com/dinosaurs");
ref.orderByChild("height").equalTo(25).on("child_added", function(snapshot) {
console.log(snapshot.key());
});
When applied to your question, it translates to:
var ref = new Firebase('https://<your-app>.firebaseio.com/user');
var things = ref.child(yourUserId).child('things');
var query = things.orderByChild('feature').equalTo('something');
query.on('child_added', function(snapshot) {
console.log('The value of the thing is now: '+JSON.stringify(snapshot.val()));
// We can remove this node with
// snapshot.ref().remove
// This will fire a child_removed event
// We can update this node with
// snapshot.ref().update({ name: 'Linda H' });
// This in turn will fire a child_changed event
});
As mentioned in the comment, the child_added event will fire for both existing child nodes and for nodes that are added after you run the query. Essentially it fires for anything that is new to the query.

Query entire class vs first object in the class

In my cloud code I want to retrieve the first object in the "Messages" class. Then i want to grab some information from that object, send it to another class, and finally delete that object from the "Messages" class i originally pulled it from.
My question is do i need to query the entire "Messages" class just to get the first object in it? I don't want to slow down my app due to inefficient code.
Parse.Cloud.afterSave("sendMessage", function(Parse.Message, response) {
var body = null;
var senderName = null;
var senderId = null;
var randUsers = [];
var query = new.Parse.Query(Parse.Message);
query.find({
success: function(results){
body.push(results[1].get("messageBody"));
senderName.push(results[1].get("senderName"));
senderId.push(results[1].get("senderId"));
response.success(getUsers);
},
error: funtion(error){
response.error("Error");
}
});
});
to avoid confusion: "getUsers" is an arbitrary function call.
To retrieve entry from class, you need the query the table. However, your problem is getting the first record which does not require getting the all record. From your code I can see that you get the first record of result array (result[1] ). You can apply the solution; getting the first record of the class that you want to query. You can do it via two ways; either you can set the limit 1 to your query or you can use the first() method. The Parse.Query JS API link is below;
https://parse.com/docs/js/symbols/Parse.Query.html
Check the limit and first methods.
Hope this helps.
Regards.

Categories