Firestore: get an Observable doc from another field which is not the Id - google-cloud-firestore

I want to get a single Observable from a collection, but I want to get it from a different field that is not the id. It is possible?
I do not want to do a query and limit to 1. I need to get a Single Observable not an array Observable.
Schema:
Code:
this.afs.doc<Credit>('credits/uid/'+ uid).valueChanges();
Error:
Invalid document reference. Document references must have an even number of segments, but credits/uid/d1Zt8sozYqb6H27lhoJgF1Gx2Cc2 has 3

I am not sure if I understand correctly, but I guess that you want to get document with particular uid field value, not using document id.
This particular error is related with common feature of Firestore, that every document has to be in collection not in document. So path values for documents, (nested as well) are always checked, if the segments (devided by /) number is even ex. collection1/doc1/collection2/doc2/collection3/doc3
As results in your code we have 3 segments (like credits/uid/<uid_value>) so this is the error.
I am not very familiar with angularFire2 itself, but I have done it in JS. The approach is normally to query collection and than use method on the results, which in classic JS returns Query object on which the same methods can be used as on CollectionReference (which extends 'Query' btw - reference 1).
Combining this approach with those references: querying and collection I propose following solution:
this.afs.collection('credits', ref => ref.where('uid', '==', <uid_value>)).valueChanges()
If uid_value will be unique you should get your doc.
Unfortunately I do not have any playground to test the solution so please let me know how it works - or if there will be any additional errors.
I hope it will help! Good Luck!

Related

Firestore check if array in specific document contains a value

I would like to check if the array "devices" which is in the document "SOjTxEjMwb71isiiPnR8" contains the value "AE0EBAFA-1560-404B-A3DA". I just want to know this specific array in the specific document. Because it can be that the same value in the same array occurs in another document. How do I have to do this in Swift? Thanks a lot for your help.
You're looking for the array-contains operations, which in Swift looks like this:
devicesRefRef
.whereField("devices", arrayContains: "AE0EBAFA-1560-404B-A3DA")
You can then get the results once or listen for realtime updates. You'll note that all links I provide are to the relevant sections of the documentation, so I recommend spending some time there.

How to create a composite index in Firestore with document Id

So I'm using firebase cloud firestore with swift (but this is a general question with firestore), and I want to sort through some documents using a query, something like
fetchQ.whereField(fieldName, isGreaterThan: startingValue)
But then I want to guarantee some kind of order if the field has the same value, and it stands to reason that the document id is good for this, so I add
.order(by: FieldPath.documentID(), descending: false)
But now I get the error in the console where I have to paste the url in order to create a composite index. I do that, except it's only for the single index "fieldName", leaving out the document id, so obviously I get an error for trying to create a composite index with a single field. I also tried it with two fields plus the document id, and sure enough the url generates a composite index for the two fields but leaving out the document id.
The composite indexing page in the firebase console also does not have an option to create a composite index involving the document id.
So it would seem to me that maybe using document id for sorting is not the intended practice? Should I create a unique id for each document for sorting purposes or if I can use document id for ordering how should I do it?
From the docs: "By default, a query retrieves all documents that satisfy the query in ascending order by document ID" (firebase.google.com/docs/firestore/query-data/…). So the behaviour you want to to achieve is what you get out of the box.

Firestore: Where query (==) on map field

I have a collection with shipments in them.
I want to filter on postalcode which is a part of the 'address_from' map.
Is this possible and are there extra steps required, indexes for example, to make this work?
query.where('address_from.postalcode', '==', shipment_code);
That query should just work. Any single field query should work without creating an index, as all fields are indexed by default. Queries that require an index will yield and error message telling you that one needs to be created, and provide a link to the console to automatically do that.

Basic MongoDb Retrieval

I have two "documents" that I inserted into my MongoDB database.
questionsList.insert({question: "When was the War of 1812", answer: "1812", answers: ["1811", "1812", "1813", "1814"]})
questionsList.insert({question: "What year did the US land on the moon?", answer: "1969", answers: ["1969", "1970", "1971", "1972"]})
I simply want to access the answer value from the second document. I have been reading the documentation and it doesn't seem to work. I can retrieve the answer value from the first document without issue: var str = questionsList.findOne({}, {question: 1}).answer; I presume that since I am using findOne I can't find any other matches. The problem is that I can't seem to pull up the second document and its corresponding answer. I have tried many different ways:
questionList.find({}, {answer: 1})
questionList.find({answer: 1})
questionList.find({}).answer
My ultimate goal is to compare this answer with one of the click one answers from choices What am I missing?
If I understood your scenario correctly, you are trying to retrieve a document based on the document index (Which is not the right thing to do, since MongoDB does not store documents in specific order).
The reason why findOne works is, because it just returns the first document in your collection.
What I believe you should do instead is retrieve the answer based on the question. Something like:
db.questionsList.find({question:"What year did the US land on the moon?"},{answer:1})
Update:
In the case of meteor.js
questionsList.find({question:"What year did the US land on the moon?"}).fetch()[0].answer
The reason whey we need to give [0] is fetch() returns an array of objects. (Since there can be multiple documents with same key)
The final step is:
questionsList.find({"question": "You are human"}, {"answer": 1}).fetch()[0].answer
We are treating it as any other object (i.e. the first within a list of objects and using dot-notation)

What's the easiest way to return the results of a query for a given key/value pair in mongo as an array of the values returned?

I have a field called id (not _id) in documents from two collections. I need to compare the contents of the first collection with the second. Basically, I need to know what documents with a given value 'id' exist in collection 'A', but not 'B'. What's the easiest way to build an array of id's from Collection A that I can use to do something like the following. :
db.B.find({id:{$nin: array_of_ids_from_coll_A}})
Please don't get hung up over why I'm using 'id' in this case, and not '_id'. Thanks.
Strictly speaking, this doesn't answer the question of 'how to build an array that...', but I'd iterate over collection A and, for each element, try to find a match in B. If none is found, add to a list.
This has a lot of roundtrips to the database, so it's not very fast, but it's very simple. Also, if A contains a lot of elements, the array of ids might be too large to throw all of them in the $nin, which otherwise would have to be solved by splitting up the array of ids. To make matters worse, $nin isn't efficient with indexes anyway.
I incorrectly assumed that the function 'distinct' returned a set of distinct documents based on a given 'field'. In fact, it returns an array of distinct values, provided a specific field. So, I was able to construct the array I was looking for with db.A.distinct('id'). Thanks to anyone who took the time to read this question, anyway.