Can't set KeyConditionExpression parameter in DynamoDb for Android - android

I'm using the Amazon AWS DynamoDB for android, however, there's no way for me to set the KeyConditionExpression for a query.
See [http://docs.aws.amazon.com/AWSAndroidSDK/latest/javadoc/com/amazonaws/mobileconnectors/dynamodbv2/dynamodbmapper/DynamoDBQueryExpression.html][1]. The DynamoDBQueryExpression class is missing a withKeyConditionExpression() method.
I'm trying to make a query against dynamodb table but there's no way for me to set the key condition values.

Unfortunately keyConditionExpression No Longer exist for Java / Android. I wasted a significant amount of time because it still exist for Objective-C / iOS.
And since all AWS docs still refer to it, I thought I was in error. Once I have the new code written and working, I will document the replacement here.

The keyConditionExpression is set as follows:
AWSDynamoDBQueryExpression *queryExpression = [AWSDynamoDBQueryExpression new];
queryExpression.keyConditionExpression = #"#bookId = :bookId";
queryExpression.expressionAttributeNames = #{
#"#bookId" : #"bookId",
};
queryExpression.expressionAttributeValues = #{
#":bookId" : self.selectedBookId,
};

I encountered the similar problem for my Android Application where .withKeyConditionExpression() method was giving an error. Instead of that, I used:
TestTable object = new TestTable();
object.setHashKeyValue("12345"); //Set the value for HashKey
String queryString = "soverflow";
Condition rangeKeyCondition = new Condition() .withComparisonOperator(ComparisonOperator.BEGINS_WITH.toString())
.withAttributeValueList(new AttributeValue().withS(queryString.toString()));
DynamoDBQueryExpression newQueryExpression = new DynamoDBQueryExpression()
.withHashKeyValues(object)
.withRangeKeyCondition("AttributeName", rangeKeyCondition)
.withConsistentRead(false);
PaginatedQueryList<TestTable> result = mapper.query(TestTable.class, newQueryExpression);
The Point is that If you are Querying a table, the HashKey and the RangeKey will be the Partition Keys of the table and If you are Querying an Index, the Hash Key and the Range Key will be the partition keys of the Index.
Make sure to use the Annotations properly in the Table Class and to add Index's ARN to the Policy for authorization.

Related

Document references must have an even number of segments error on a collection reference

I'm getting the rather simple error:
Document references must have an even number of segments.
I'm aware of what it is telling me and how to fix it, however it is giving me this error on a collection reference.
CollectionReference collectionReference = getFirebaseInstance()
.collection(Constants.USERS)
.document(userId)
.collection(Constants.CONTACTS);
In my database the path is (COLLECTION) < DOCUMENTS > (COLLECTION) < DOCUMENTS > I'm trying to get all contacts for a user at users/{id}/contacts but it just throws this error, any ideas?
getFirebaseInstance is a method I've created to always get the current
FirebaseFirestore.getInstance();
Your userId variable probably has a slash in it. Document ids can't have slashes, since they are interepreted as dividers between collections and documents when forming the "path" to a document.
It's also possible that the string may be empty, which is invalid.
I found the same problem, this is what solved my problem :
I tried to set a document using the :
setDoc()
without providing the document id.
So I used :
addDoc()
so firebase itself provide an id for document.
The lecon is that :
using set you must provide an ID, using add you do not have provide the ID firebase do it for you.
Thanks !
Because neither the above nor other similar posts helped me..
I got this error when calling set data and then immediately after .getDocument(...) (i.e. reading data). When I called my read data method in the completion handler of the setData method then the error message disappeared.
i'm not sure that's your case ,But, if you have a function like this, that brings data by "Id" from your firebase , just add a slash "/" after your collection's name
getDetailProduct(id: string): Observable<Interface_name> {
const productsDocuments = this.angularFirestore.doc<Interface_name>(
'collection_name/' + id //here after your collection name add "/"
);
return productsDocuments.snapshotChanges().pipe(
map((changes) => {
const data = changes.payload.data() as Interface_name;
const id = changes.payload.id;
return { id, ...data };
})
);
}

android firebase unable to add second child

My code:
btnSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
NewQuestionData nqd = new NewQuestionData(question.getText().toString(),keywords.getText().toString(),description.getText().toString());
databaseReference.child(firebaseUser.getUid()).child("question"+Math.random()).setValue(nqd);
}
});
Every time I insert value into the database, it fails.
Problem is here:
child("question"+Math.random())
I want to add unique ID with every question.
Following works fine:
child("question")
Please share your valuable suggessions, How to insert unique child for every new question inserted into the Firebase Database.
Try this.
String key = databaseReference.child(firebaseUser.getUid()).child("question").push().getKey();
databaseReference.child(firebaseUser.getUid()).child("question").child(key).setValue(nqd);
// key is unique every time you add your new question.
For more info you can visit https://firebase.google.com/docs/database/android/read-and-write
OR
you can use System.currentTimeMillis()
It will give timestamp in long and is always unique.
databaseReference.child(firebaseUser.getUid()).child("question"+System.currentTimeMillis()).setValue(nqd);
The problem is that the random generator function Math.random() generates values between 0 and 1 which would have the decimal point - .
Now this decimal when added to a string would look something like question0.0001
If you check the Firebase documentation, you would see that . is a forbidden character in a key. So this would be your problem. If you at all want to generate a random value, use something which will generate random values from 0 to INTEGER_MAX.
To insert a child with a unique key without having to worry about it, call Firebase's push() method. See the Firebase documentation on appending data.
Your code could be:
databaseReference
.child(firebaseUser.getUid())
.push()
.setValue(nqd);
This will generate a unique key of the format specified in this blog post: The 2^120 Ways to Ensure Unique Identifiers.
If you still want to use the question prefix, you can use push() as a separate call (it's a client-side call that doesn't connect to the Database):
String key = databaseReference.push().getKey(); // gets a unique ID
databaseReference
.child(firebaseUser.getUid())
.child("question"+key)
.setValue(nqd);

Possible to query against the count of an included key?

I have an application where I need to return the first user found that meets certain criteria, some of that criteria is having a certain number of objects stored.
For example, let's say I want to return the first store I can find that has at-least 3 employees with atleast two children. I know, what an odd-ball example. So I would have a query something like this:
PFUser.query()?
.whereKey("objectId", notEqualTo: PFUser.currentUser()?.objectId!)
.includeKey("stores.employees.children")
// .whereCountForkey("stores.employees", greaterThan: 2)
// .whereCountForKey("stores.employees.children", greaterThan: 1)
.getFirstObject();
Notice the commented out lines, I'm trying to find a way to do soemthing like this in a single query. I'm using parse, which I believe uses MongoDB on the back end, but I don't believe you can execute custom database queries..?
This is a mobile application for both iOS and Android, although the code shown is in SWIFT I have two variations of the project. Examples in either swift, obj-C, Java, or C# will be fine.
Also more than happy with Cloud-code solutions.
There is an example in the documentation
var Team = Parse.Object.extend("Team");
var teamQuery = new Parse.Query(Team);
teamQuery.greaterThan("winPct", 0.5);
var userQuery = new Parse.Query(Parse.User);
userQuery.matchesKeyInQuery("hometown", "city", teamQuery);
userQuery.find({
success: function(results) {
// results has the list of users with a hometown team with a winning record
}
});

How to update list of records with special characters into sqlite table using ormlite in Android

I am using ormlite for database operations in my Android app. I want to update around 1000 records at a time. But, if these records have any special characters such as ' / \ % , I am getting the following exception.
java.sql.SQLException: Problems executing Android statement: UPDATE `staticresource`
SET `Content` = 'Tick next to member and add by clicking on \'Invite Selected\'
button to create invite list.' ,`Id` = '3' WHERE `Alias` = 'tm'
So, how to update these records optimally. Thanks in advance.
You can escape special character's using
DatabaseUtils.sqlEscapeString();
String updateString = DatabaseUtils.sqlEscapeString("Tick next to member and add
by clicking on \'Invite Selected\' button to create invite list.");
updateString can be pass to ormlite update method.
How to update these records optimally.
The right thing to do is to use the UpdateBuilder combined with a SelectArg (which is a poor name). The SelectArg will use the ? SQL feature in which case your string can include special characters without issue.
UpdateBuilder ub = dao.updateBuilder();
updateBuilder.where().eq("Alias", "tm");
updateBuilder.updateColumnValue("Content",
new SelectArg("... on \'Invite Selected\' button to ..."));
updateBuilder.update();
This will generate something like:
UPDATE `staticresource` SET `Content` = ? WHERE `Alias` = 'tm'
And it will set the ? value to be your string. You don't need to worry about escaping anything. This is also how you protect user input from SQL injection attacks.

Query where "Number" column value is empty or is greater than X

I am trying to provide a database-type Android for my users, where I'd like to take the following precausion for future compatibility: make certain rows/elements only available "since version X" of the app.
All versions of the app will query for entries and provide their version code in the query.
Now, I can successfuly retrieve rows that are supported in the current version using:
query.whereLessThanOrEqualTo("sinceVersion", getCurrentAppVersionCode(this));
However, this does not account for and retrieve rows that have empty value for "sinceVersion".
You can solve your problem with compound query
ParseQuery<TestParse> queryLessEqual = ParseQuery.getQuery(TestParse.class);
queryLessEqual.whereLessThanOrEqualTo("sinceVersion", getCurrentAppVersionCode(this));
ParseQuery<TestParse> queryDoesNotExists = ParseQuery.getQuery(TestParse.class);
queryDoesNotExists.whereDoesNotExist("sinceVersion");
ParseQuery<TestParse> compoundQuery = ParseQuery.or(Arrays.asList(queryLessEqual, queryDoesNotExists));
List<TestParse> list = compoundQuery.find();
where TestParse is your class from Parse.com

Categories

Resources