Im really confused on how to query a single record in firebase by the uid.
I have a user id and want to query the following table. I am using the following code.
However, it is returning both the records instead of just the 'this.selectedId' one. Is there 1) A way to just return the record being queried 2) keep the key instead of array of index 0, 1, 2, 3 etc...
Code used
const itemsRef = this.afs.collection<any>(`/profiles/`);
itemsRef.valueChanges(this.selectedId).subscribe(
x => {
console.log("Value change", x);
}
);
Image
Returned result
The valueChanges method doesn't take any parameters. If you want to monitor a single document
const itemRef = this.afs.doc<any>(`/profiles/`+this.selectedId);
itemRef.valueChanges()...
Related
I don't think I'm very far from the answer, I tried to query an id inside an array on Firestore.
I wanna compare the id of the participants.
Also my DB in Firestore:
And also my function, for the moment my function return size =0 so they can't catch the query.
const deleteAbuse = (type) => {
const participants = channel?.otherParticipants;
if (!participants || participants.length != 1) {
return;
}
const myID = currentUser.id;
const otherUserID = participants[0].id;
console.log('id user', otherUserID);
channelDB
.where('participants.id', '==', otherUserID)
.get()
.then((querySnapshot) => {
console.log(querySnapshot.size);
querySnapshot.forEach((doc) => {
console.log(doc.ref);
//doc.ref.delete();
});
});
};
There is no way you can query filter your "channels" collection to get documents based only on a single field of an object that exists inside the participants array. In other words, you cannot create that filtering based only on that ID. To be able to filter the data, you should pass to the where() function, the entire object, and not only some partial data. The object should contain values for all the fields. Only the ID is not enough.
And also my function, for the moment my function return size =0
That's the expected behavior since in your array there isn't any object that holds only a single field called id. All objects hold 7 fields, or even more than that, as I cannot see all fields in your screenshot.
I wrote an article called:
How to update an array of objects in Firestore?
Where you can find in the first part, the simplest way to get a custom object from an array of custom objects.
Alternatively, you can create an array that can hold only the IDs of the participants, filter the documents and create another database call to get their corresponding data.
I have a firebase collection called activity with 4 documents inside, with timestamps of 2, 3, 4, and 5 o'clock.
When I query it like so
let postsQuery = firebase
.firestore()
.collection(`activity`)
.orderBy("timestamp", "desc")
.limit(2);
I correctly get the 5 and 4 o'clock posts.
However, when I call the function again with the following conditional:
// oldest post is the 4 o'clock document
if (oldestPost) {
postsQuery = postsQuery.startAfter(oldestPost);
}
I get the 4 and 5 documents again. If I change startAFter to be any other filter, I get 0 documents returned.
So my question is, am I just doing it wrong, OR can I not pass in a document.data() as the filter, and i need to pass in the original document instead?
So answering my own questions:
when i got my posts, I was just storing them in an idMap
postsQuery
.get()
.then((documents) => {
const typeIdToDocument = {};
documents.forEach((document) => {
const data = document.data();
typeIdToDocument[document.id] = { id: document.id, ...data };
});
Then when I passed in an startAfter, I used the .data() result of the post.
However, it worked when-
A) I passed in the original firebase document, not the .data() version
OR B) I passed in the Firebase Timestamp, rather than the full document
postsQuery = postsQuery.startAfter(oldestFirebaseTimestamp);
There are two overloads of startAfter:
startAfter ( snapshot : DocumentSnapshot < any > ), which is the one I recommend you use whenever you can
startAfter ( ... fieldValues : any [] ), into which you can pass just the field values of the document to start after.
The reason I recommend the first overload is that there may be cases where you have multiple documents with the same field value. The first overload is smart enough in that case to use the document ID to disambiguate between those and not return any overlapping documents. The second overload can't guarantee that.
I'm attempting to create this structure in firebase:
inMinistries
--uidOfGroup1
----0: uidOfGroup1Member
----1: uidOfGroup1Member
----2: uidOfGroup1Member
--uidOfGroup2
----0: uidOfGroup2Member
----1: uidOfGroup2Member
In the above example inMinistries is the first node, then we have uidofGroup1 which would be a uid of a Group then I want child nodes to appear like uidOfGroup1Member. There are several so I can't say exactly how many I need.
Here is my attempt to create the above:
class Firebase {
constructor() {
app.initializeApp(firebaseConfig);
this.auth = app.auth();
this.db = app.database();
this.storage = app.storage();
}
This is how I set the uidOfGroups
this.db.ref(`inMinistries/${uidOfGroup}`).set('members')
I pass a uid value I receive from another call. I set 'members' so that I could replace it with a group of members later.
I then try to create uidOfGroup1Members, uidOfGroup2Members. I get stuck on this part. If I do a set like so:
this.db.ref(`/inMinistries/${uidOfGroup}}`).set(memberId);
I can only pass the memberId once, meaning I'd need to have the full list of uidOfGroupMembers which I don't have all at once. I'd like to be able to push it like I would in an array. But if I do push:
this.db.ref(`/inMinistries/${uidOfGroup}}`).push(memberId);
then it adds an extra uid to the value before like so:
Note the above is actually using the uids. How can I achieve the original desired result I placed on top?
If you have no constraint on how you save the different uidsOfGroupMember under a specific uidOfGroup (in particular no need for using a specific "index" (i.e. 0, 1, 2)), you could use the set() method as follows:
var uidOfGroup = 'uidOfGroup1';
var uidOfGroup1Member = 'uidOfGroup1Member'; //Of course, here you can assign the value you want, e.g. -Lwk98a...
this.db.ref(`/inMinistries/${uidOfGroup}/${uidOfGroup1Member}`).set(
uidOfGroup1Member
);
var uidOfGroup2Member = 'uidOfGroup2Member';
this.db.ref(`/inMinistries/${uidOfGroup}/${uidOfGroup2Member}`).set(
uidOfGroup2Member
);
One difference between the push() and the set() methods is that push() creates a child location with an auto generated unique key, which is the cause of your problem.
I am trying to find out how to get a user list via their id in tabular form (array).
I've tried this :
let result = message.guild.members.get(id_list)
But it doesn't work ...
id list :
var id_list = [ '223515154229231616',
'447425491041910807',
'479932358422691840',
'464536970417143828',
'299429099611357185',
'332868897646837762',
'198346639843262464',
'266078466972057600',
'334270225895653379',
'198884536363253761',
'216595784286601216',
'358993909269135371',
'248894149162565647',
'396681438688182284',
'349270173011804171',
'358319021726236672',
'216136890963853313',
'282994966014459915',
'298171616968572930',
'257809919036751872',
'239365876846034944',
'502162147942596609',
'449391921840914444',
'473229490584158208' ]
The following should do the trick
let result = id_list.map(id => client.users.get(id));
Basically, you loop through all the ids you have using .map() and fetch the user associated.
You may want to remove all the undefined results (when your bot "does not know" the user linked to a specific id), in that case you need to add the following after the previous piece of code :
result = result.filter(r => r !== undefined);
Check both the documentation of .map() and .filter() for more information
This will not work as it is for one ID at a time, not an array of them. You would need to iterate over the IDs in the array, I suggest using a for loop for this, using id_list.length as one of the parameters. For example:
for(var i = 0; i <= id_list.length; i++) {
//make the request to get the member information
}
Also, just to make sure, you might be better off using client.users.get('id'); because if the user sends a direct message, there is no guild property so an error will be thrown.
You can use
let result = id_list.map(id => client.users.get(id).tag)
That should give back an array with like
['User#0000',
'NextUser#4821'
]
I am working a lot with firebase, and am trying to load certain information from the database. The original data comes from a query, and is returned to me in a POJO. The console prints this when the original data is returned:
-KhQ76OEK_848CkIFhAq: "-JhQ76OEK_848CkIFhAq"
-OhQ76OEK_848CkIFhAq: "-LhQ76OEK_848CkIFhAq"
What I need to do is grab each of the values (-JhQ76OEK_848CkIFhAq and -LhQ76OEK_848CkIFhAq) separately, and query the real-time database again for each one. I can manage that aspect, but I cannot seem to figure out how to separate the values.
I have already tried to get a single output by doing:
console.log(vals[0]) but it just returned undefined, and splitting the string by " would be very inefficient for large data sets. Any ideas?
To access the values, you can iterate the snapshot's children using the snapshot's forEach method. The keys and values of the children can be obtained using the key property and the val() method:
firebase.database()
.ref("some/path")
.once("value")
.then((snapshot) => {
snapshot.forEach((childSnapshot) => {
console.log(childSnapshot.key); // The child's key: e.g. "-KhQ76OEK_848CkIFhAq"
console.log(childSnapshot.val()); // The child's value: e.g. "-JhQ76OEK_848CkIFhAq"
});
});
To solve this issue, all I did was convert the object returned into an array by using this code below:
var Array = Object.keys(datalist).map(function(k) { return datalist[k] });
Works like a charm, and I can now run a simple for loop for Array