How to avoid empty documents in a Firestore query? - java

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.

Related

Problems with Google Firestore collectionGroup - whereArrayContains

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.

How do I query a user's info in Firestore if all my document IDs are auto-generated?

All of the examples I'm finding online have very simple document IDs, but what do you do if you're auto-generating all your IDs (as the docs say you should)? For example, I want to query the date when the user was created. The document ID for this is below, but I've just copy-pasted it from the Firestore console. How would I know the document ID so that I may query any user's info? Note that I will be have a users, groups, usergroups, etc... There will be quite a few collections, each using the auto-ID feature. I would need to be able to update any row in any collection.
val docRef = db.collection("users").document("9AjpkmJdAdFScZaeo8FV45DT54E")
docRef.get()
.addOnSuccessListener { document ->
if (document != null) {
Log.e("Query", "Data: ${document.data}")
} else {
Log.e("Query", "Document is null")
}
}
.addOnFailureListener { exception ->
Log.e("Query", "Failure")
}
If you have data to query, that should all be stored as fields in the documents. Don't put that data in the ID of the documents - use field values.
You can filter documents in a collection using "where" clauses as shown in the documentation. What you're showing here isn't enough to go with in to make specific recommendations. But you definitely want to think about your queries ahead of time, and model your data to suit those queries.
If you need to update a document, you must first query for it, then update what you find from the query. This is extremely common, as Firestore does no provide any SQL-like "update where" queries that both locate and update data in the same command.

Lucene 6 How to avoid duplicate entries

Story:
I need to search for a list of transactionIds be a given username query e.g "Peter M*".
Question: How is it possible to keep the stored transactionIds unique?
I have populated my index with following documents:
Document doc = new Document();
doc.add(new StoredField(TRANSACTION_ID, data.getTransactionId()));
doc.add(new TextField(MARCHANT_NAME, data.getName(), Store.NO));
I have tried allready two strategies (to avoid duplicate entries) to add a new entry.
IndexWriter.updateDocument with a Term holding the transactionId to store.
Search for the current transactionId, delete it and store it:
You are using a StoredField for the TRANSACTION_ID field. That means it can be retrieved from the index, but is not indexed and can't be searched, and as such, it can't be used as a key to updateDocument. Use a StringField, instead.

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.

Java method for MongoDB collection.save()

I'm having a problem with MongoDB using Java when I try adding documents with customized _id field. And when I insert new document to that collection, I want to ignore the document if it's _id has already existed.
In Mongo shell, collection.save() can be used in this case but I cannot find the equivalent method to work with MongoDB java driver.
Just to add an example:
I have a collection of documents containing websites' information
with the URLs as _id field (which is unique)
I want to add some more documents. In those new documents, some might be existing in the current collection. So I want to keep adding all the new documents except for the duplicate ones.
This can be achieve by collection.save() in Mongo Shell but using MongoDB Java Driver, I can't find the equivalent method.
Hopefully someone can share the solution. Thanks in advance!
In the MongoDB Java driver, you could try using the BulkWriteOperation object with the initializeOrderedBulkOperation() method of the DBCollection object (the one that contains your collection). This is used as follows:
MongoClient mongo = new MongoClient("localhost", port_number);
DB db = mongo.getDB("db_name");
ArrayList<DBObject> objectList; // Fill this list with your objects to insert
BulkWriteOperation operation = col.initializeOrderedBulkOperation();
for (int i = 0; i < objectList.size(); i++) {
operation.insert(objectList.get(i));
}
BulkWriteResult result = operation.execute();
With this method, your documents will be inserted one at a time with error handling on each insert, so documents that have a duplicated id will throw an error as usual, but the operation will still continue with the rest of the documents. In the end, you can use the getInsertedCount() method of the BulkWriteResult object to know how many documents were really inserted.
This can prove to be a bit ineffective if lots of data is inserted this way, though. This is just sample code (that was found on journaldev.com and edited to fit your situation.). You may need to edit it so it fits your current configuration. It is also untested.
I guess save is doing something like this.
fun save(doc: Document, col: MongoCollection<Document>) {
if (doc.getObjectId("_id") != null) {
doc.put("_id", ObjectId()) // generate a new id
}
col.replaceOne(Document("_id", doc.getObjectId("_id")), doc)
}
Maybe they removed save so you decide how to generate the new id.

Categories

Resources