background: I am trying to retrieve one document from a collection with a value rather than it's ID. I'm basically trying to make a login system.
I tried this solution: Firestore : Retrieve a single document
using flat-map to and limit(1) to do it but it does not seem to give anything, this is what my code looks like right now:
this.user = this.afs.collection('users/', ref => ref.where('username',
'==', this.username).limit(1)).valueChanges().flatMap(result => result);
console.log(this.user.username);
the output is undefined, though if I do just print the user I do get the observable
You should be setting this.user
to the Observable reference and then subscribing to it like so:
this.user = this.afs.collection('users', (ref) => ref.where('username', '==', this.username).limit(1)).valueChanges();
// I removed the slash after 'users' as it isn't necessary
Then subscribe to that Observable like so:
this.user.subscribe((user) => {
console.log(user);
});
Which should give you back only one result. Console Logging the Observable will not display the data but log the Observable object.
Keep note that you should have the userId that correlates with that username and fetching a document instead as it will be more secure and more definite than fetching a collection that matches a field and limiting it to 1. If this is matter of authentication, you should be using Firebase Auth and using whatever form of authentication as the username and Firebase Auth will handle not having duplicate logins. If desired to use usernames instead of an email, you can request but your method should just return the length of your request like so:
this.user = this.afs.collection('users',
(ref) => {
return ref.where('username', '==', this.username).limit(1)
})
.snapshotChanges()
.map((users) => {
return users.length
});
This way you are not returning the user object in your request but instead returning a number and if it is greater than zero, a user already has that username.
Since you are using valueChanges()
instead of snapshotChanges()
it seems as you do not need to manipulate the data before displaying it on the DOM so you do not need to subscribe to the data but instead subscribing to the Observable using the ASYNC pipe in your markup. This is a question I asnwered the other day which explains your issue here as well as using the ASYNC pipe in your markup: Angular Observable Array Object Conversion