Problems with Google Firestore collectionGroup - whereArrayContains - java

I'm working on an Android App written in Java.
I'm trying to query for documents in Cloud Firestore using collectionGroup and whereArrayContains.
My structure in Cloud Firestore looks like this:
Teams (collection)
- teamUUID (document)
- reservations(collection)
- reservationDate (document)
- places (collection)
- userUUIDs (array of strings)
-> one entry ->"vQn9vbWzTtcsB71hgPBhX2uWBuI3"
- placeID (document)
partial screenshot of the structure
I want to get all documents in the collection places, where the userUUIDs field contains a specific string. My code for this is the following:
db.collectionGroup("places")
.whereArrayContains("userUUIDs",
"vQn9vbWzTtcsB71hgPBhX2uWBuI3")
.get()
.addOnSuccessListener(queryDocumentSnapshots -> {
Log.d(TAG, String.valueOf(queryDocumentSnapshots.getDocuments().size()));
if (queryDocumentSnapshots.isEmpty()) {
//nothing found
Log.d(TAG, "nothing found for this user");
If this code is executed, the query is successful, but no documents are returned.
If I leave out .whereArrayContains("userUUIDs", "vQn9vbWzTtcsB71hgPBhX2uWBuI3"), one document is returned.
Google Firestore automatically created the index to query for "userUUIDs".
index created in firestore
Why are there no documents returned using whereArrayContains?
Edit:
The problem seams to exist with all queries.
I added a string testValue to places and made a whereEqualTo Query. The result was the same. After creating an index (automatically via link in the console) the onSuccessListener code was executed, but no document was found.
Thanks in advance.

Why are there no documents returned using whereArrayContains?
Because you most probably didn't create the correct index. If the userUUIDs exists within the documents from the "places" collection, when running the app you'll find a message like this in the logcat:
Caused by: io.grpc.StatusException: FAILED_PRECONDITION: The query requires a COLLECTION_GROUP_CONTAINS index for collection places and field userUUIDs. You can create it here: https://console.firebase.google.com/v1/r/project/...
You can simply click on that link or copy, and paste the URL into a web browser and your index will be created automatically.

Related

How to search in firebase database

I'm trying to filter the data from my database using this code:
fdb.orderByChild("title").startAt(searchquery).endAt(searchquery+"\uf8ff").addValueEventListener(valuelistener2);
My database is like this:
"g12" : {
"Books" : {
"-Mi_He4vHXOuKHNL7yeU" : {
"title" : "Technical Sciences P1"
},
"-Mi_He50tUPTN9XDiVow" : {
"title" : "Life Sciences"
},
"-Mi_He51dhQfl3RAjysQ" : {
"title" : "Technical Sciences P2"
}}
While the code works, it only returns the first value that matches the query and doesn't fetch the rest of the data even though it matches.
If I put a "T" as my search query, I just get the first title "Technical Sciences P1 " and don't get the other one with P2
(Sorry for the vague and common question title, it's just I've been looking for a solution for so long)
While the codes works, it only returns the first value that matches the query
That's the expected behavior since Firebase Realtime Database does not support native indexing or search for text fields in database properties.
When you are using the following query:
fdb.orderByChild("title").startAt(searchquery).endAt(searchquery+"\uf8ff")
It means that you are trying to get all elements that start with searchquery. For example, if you have a title called "Don Quixote" and you search for "Don", your query will return the correct results. However, searching for "Quix" will yield no results.
You might consider downloading the entire node to search for fields client-side but this solution isn't practical at all. To enable full-text search of your Firebase Realtime Database data, I recommend you to use a third-party search service like Algolia or Elasticsearch.
If you consider at some point in time to try using Cloud Firestore, please see the following example:
Is it possible to use Algolia query in FirestoreRecyclerOptions?
To see how it works with Cloud Firestore but in the same way, you can use it with Firebase Realtime Database.

Elasticsearch update document without creating new index

I have many existing indices partition by date. Eg: index_190901, index_190902,...
And I have an API which takes index_name and doc_id as inputs. User want to update some documents in index by input fields, index_name, doc_id.
I'm trying to update document using the following code:
updateRequest.index("invalid_daily_index")
.type("type")
.id("id")
.doc(jsonMap)
It works fine if user input existing index but if user input non-existing index, new index with no document will be created.
I know that I can setup auto_create_index but I still want to create index automatically when I insert new documents.
Check if index is existed with client.indices.exists(request, RequestOptions.DEFAULT) is quite expensive. I don't want to check it every request
How to make Elasticsearch to not create new index when I use updateRequest.
You can block the option to automaticaly create non existing indices by putting false to the action.auto_create_index setting of the cluster
PUT _cluster/settings
{
"persistent" : { "action.auto_create_indexā€¯ : "false" }
}
For details take a look at the reference

How to evolve schema in Janusgraph?

I uploaded movie and user data to janusgraph and initially I made index on movieId but, later I realised I need to index movie title as well. I need to do query based on movie title and without indexing movie id, it's giving me warning "Query requires iterating over all vertices". So, I added the code:
JanusGraphManagement mgmt = graph.openManagement();
PropertyKey title = mgmt.getPropertyKey("title");
JanusGraphManagement.IndexBuilder movieNameIndexBuilder = mgmt.buildIndex("title", Vertex.class)
.addKey(title);
movieNameIndexBuilder.unique();
JanusGraphIndex movieTitleIndex = movieNameIndexBuilder.buildCompositeIndex();
mgmt.setConsistency(movieTitleIndex, ConsistencyModifier.LOCK);
mgmt.commit();
Still I'm getting the same warning "Query requires iterating over all vertices" when I'm querying on movie title.
Thank you
Got the solution from Janusgraph gitter channel:
The index isn't available immediately if the the indexed property key was created in a previous management transaction as JanusGraph might need to reindex existing data now. That is a process you have to trigger manually. You can read more about this in the chapter Index Management of the docs.
That is why it's recommended to create all indices in the same transaction where you create the property keys if possible

How to avoid empty documents in a Firestore query?

I'm trying to display some data which is hosted under a subcollection coll1 that exist in doc1 using this code:
val query = db!!.collection("coll1").document(doc1)
.collection("coll2").orderBy("field1", Query.Direction.ASCENDING)
The problem is when I use this code, the doc1 variable isn't generated yet so I get this error:
Invalid document reference. Document references must have an even number of segments
How can I avoid this error till I generate doc1?
You need to know the exact names of all collections and documents in order to perform a query, so your query should only be performed after you have the string value for doc1 that identified the document where the subcollection has been organized.

Java Couchbase Querying to find a document's ID?

I'm new to couchbase. I'm using Java for this. I'm trying to remove a document from a bucket by looking up its ID with query parameters(assuming the ID is unknown).
Lets say I have a bucket called test-data. In that bucked I have a document with ID of 555 and Content of {"name":"bob","num":"10"}
I want to be able to remove that document by querying using 'name' and 'num'.
So far I have this (hardcoded):
String statement = "SELECT META(`test-data`).id from `test-data` WHERE name = \"bob\" and num = \"10\"";
N1qlQuery query = N1qlQuery.simple(statement);
N1qlQueryResult result = bucket.query(query);
List<N1qlQueryRow> row = result.allRows();
N1qlQueryRow res1 = row.get(0);
System.out.println(res1);
//output: {"id":"555"}
So I'm getting a json that has the document's ID in it. What would be the best way to extract that ID so that I can then remove the queryed document from the bucket using its ID? Am I doing to many steps? Is there a better way to extract the document's ID?
bucket.remove(docID)
Ideally I'd like to use something like a N1q1QueryResult to get this going but I'm not sure how to set that up.
N1qlQueryResult result = bucket.query(select("META.id").fromCurrentBucket().where((x("num").eq("\""+num+"\"")).and(x("name").eq("\""+name+"\""))));
But that isn't working at the moment.
Any help or direction would be appreciated. Thanks.
There might be a better way which is running this kind of query:
delete from `test-data` use keys '00000874a09e749ab6f199c0622c5cb0' returning raw META(`test-data`).id
or if your fields has index:
delete from `test-data` where name='bob' and num='10' returning raw META(`test-data`).id
This query deletes the specified document with given document key (which is meta.id) and returns document id of deleted document if it deletes any document. Returns empty if no documents deleted.
You can implement this query with couchbase sdk as follows:
Statement statement = deleteFrom("test-data")
.where(x("name").eq(s("bob")).and(x("num").eq(s("10"))))
.returningRaw(meta(i("test-data")).get("id"));
You can make this statement parameterized or just execute like that.

Categories

Resources