emoji look up table and algorithm - android

I am trying to build an android app that the user can enter a string, and a list emoji related to that string would show up. (Just like Venmo app) For example:
case 1: User enters "pizz", and in the list there would be "πŸ•", note that the users enter "pizz", not pizza!
case 2: User enters "rabb", and in the list there would be "πŸ‡" and "🐰", note that the users enter "rabb", not rabbit!
What would be a good data structure and algorithm for this problem?

A trie is what your looking for. From Wikipedia
A trie, also called digital tree and sometimes radix tree or prefix tree (as they can be searched by prefixes), is a kind of search treeβ€”an ordered tree data structure ...
A trie is similar to a HashMap<K,V>, you can perform a lookup with keys and get a value. The difference is that you can also search by prefix. Given a prefix, it will find all the key-value pairs in the structure that have that prefix. It's basically the data structure for generating search suggestions.
General Idea:
Trie<String, String> t = new Trie<String, String>();
t.insert("pizza", "πŸ•");
t.insert("rabbit1", "πŸ‡");
t.insert("rabbit2", "🐰");
// then later...
t.findByPrefix("rabb"); // [πŸ‡,🐰]
Unfortunately, tries are too generic and are not present in any popular data structure libraries (like Java Collections Framework or Google Guava, for example). You'd have to implement one yourself or find an existing implementation and modify it.
I'd recommend:
Learning the theory. Watch this video. There are many more on YouTube that will teach you the basics. You can also search google for "N-way trie" and read notes about it.
Taking this class TrieST and modifying it. It's very similar (or already perfect) for what you need: http://algs4.cs.princeton.edu/52trie/TrieST.java.html see specifically thekeysWithPrefix method.

Related

Migration Firestore replace field

Let's say that I have a document like this:
Document {
tags: list<Int> {0,1,2}
}
I want to change it to this:
Document {
tags: list<String> {SEASON, TRAINING, TOURNAMENT}
}
I have active users which uses the list of ints, How do I create a migration in Firestore for this problem?
One solution I have in mind is to make 2 migrations:
For creating a new tags called tagsStrings.
For deleting all users who still have tags.
But can I make it in 1?
I was unable to find documentation for this, on https://cloud.google.com/firestore/docs/manage-data/move-data
Thanks in advance
Firestore does not have a "migration" like SQL databases. The only way to modify data in existing documents, in bulk, is to:
Query for the documents to change
Iterate the results
Update each document with new values
Each one of these tasks should be straightforward.
You might also consider lazily updating each document as each are individually read during the normal course of your app's usage. So, if your app reads a document in the old format, immediately update it to the new format.
It's often helpful to have a dedicated field in each document to indicate which version of data that's contained within. So, initially set v=1 in each document, assign v=2 to mean that the document has strings instead of numbers for tags, then use that number to determine which documents have yet to be migrated.

Combining Firebase Queries with GeoQuery to search Posts by name in nearby area

I'm making an android app where user can find a book in his/her vicinity and buy it if interested. I am using firebase and geoqueries/geofire.
I want to make a SearchActivity where user can search a book by it's title in his/her vicinity.
my Firebase Database Structure looks like :
books
PushKey
g:
l:
0:
1:
name:"some book name"
If i try to query this with some book name, it works fine using :
myRef.orderByChild("name").equalTo("some book name").addChildEventListener()....//The rest of the code here...
If i try to query nearby books,then also it works fine using :
geoQuery = geoFire.queryAtLocation(myLocation, 10);
I'm stuck at combining these two.
How can i search for a specific book name only in the vicinity?
For example : I want to search a book whose name is "ABCD" and is in a radius of 10km.
OR
Search a book by name and tell which one is nearest(In case several books are uploaded with same name at different locations).
Is it possible to do so? If not, what workaround(maybe other than firebase, but has to cheap and affordable) can i opt for where i can achieve this desired result?
The Firebase Database can only query by a single property. The fact that GeoFire does something that is seemingly at odds with that (querying by longitude and latitude) is because it combines these values into a single property in a magical format called a geohash (the g property in your JSON).
Combining values into a single property is the only way to get Firebase to filter on multiple values. For example, you could prefix the g property with your book title to get some book name_geohashvalue and could then filter on that.
The two main problems with that:
This only works if you know the entire book title, you can do a prefix match on the title, as you'll already need to use the prefix match for the geohash.
This is not built in to GeoFire, so you will have to fork that library and build it yourself.
If you do try to do this yourself, and get stuck, we can try to help. But fair warning: this won't be trivial, and you'll need to understand how geohashes, geofire, and Firebase's query model work quite well. For an intro, I recommend watching the video of my talk on performing geoqueries on Firebase and Firestore.
If you want something a bit less involved, you have two main options:
Retrieve all nodes within range, and then filter for the book title client-side.
Store a separate GeoFire tree for each book title, so that you can initialize your GeoFire object based on the book title, and only get keys within range for that specific book title.
Between these two, I'd recommend starting with #1.

How to do a simple search in string in Firebase database?

I want to create a simple search in my app, but cannot find anything on interwebs about it, that's more recent than 2014. There must be a better way. There are startAt and endAt functions but they don't work as expected and are case sensitive. How do you guys solve this problem? How can this functionality still not exist in 2016?
In my case I was able to partly achieve a SQL LIKE in the following way:
databaseReference.orderByChild('_searchLastName')
.startAt(queryText)
.endAt(queryText+"\uf8ff")
The character \uf8ff used in the query is a very high code point in the Unicode range (it is a Private Usage Area [PUA] code). Because it is after most regular characters in Unicode, the query matches all values that start with queryText.
In this way, searching by "Fre" I could get the records having "Fred, Freddy, Frey" as value in _searchLastName property from the database.
Create two String variables
searchInputToLower = inputText.getText().toString().toLowerCase();
searchInputTOUpper = inputText.getText().toString().toUpperCase();
Then in the Query set it to:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Products");//Your firebase node you want to search inside..
FirebaseRecyclerOptions<Products> options =
new FirebaseRecyclerOptions.Builder<Products>()//the Products is a class that get and set Strings from Firebase Database.
.setQuery(reference.orderByChild("name").startAt(searchInputUpper).endAt(searchInputLower + "\uf8ff"),Products.class)
.build();
the "name" it's the node inside the Products Main Node.
the .startAt(searchInputUpper) & .endAt(searchInputLower + "\uf8ff") to make the search as contains all characters that typed in the inputText.getText() that you get.
finally I got it you can use where clause to get you result like SQL
LIKE keyword like% or %like
syntax :
Firestore.collection(collectionName).orderBy(field).where(field, ">=", keyword.toUpperCase()).where(field, "<=", keyword.toUpperCase() + "\uf8ff").get()
I my case used:
var query = 'text'
databaseReference.orderByChild('search_name')
.startAt(`%${query}%`)
.endAt(query+"\uf8ff")
.once("value")
In this way, searching by "test" I could get the records having "Test 1, Contest, One test" as value in 'search' property from the database.
Firebase is noSQL therefore it does not have searches built in like you'll find in SQL. You can either sort by values/key or you can equalto
https://firebase.google.com/docs/database/android/retrieve-data
You can find examples at the link above. That is the latest documentation for firebase.
If you are looking for SQL like searches. Then take a look at elastic search. But that will increase the complexity since you need a platform to put it on. For that i could recommend Heroku or maybe GoogleCloudServers
Here is a blog post about advanced searches with elastic search
https://firebase.googleblog.com/2014/01/queries-part-2-advanced-searches-with.html
This question might be old but there is a documented way of how to achieve this way, It is simple to implement. Quoted:
To enable full text search of your Cloud Firestore data, use a third-party search service like Algolia. Consider a note-taking app where each note is a document:
Algolia will be part of your firebase functions and will do all the searches you want.
// Update the search index every time a blog post is written.
exports.onNoteCreated = functions.firestore.document('notes/{noteId}').onCreate(event => {
// Get the note document
const note = event.data.data();
// Add an 'objectID' field which Algolia requires
note.objectID = event.params.noteId;
// Write to the algolia index
const index = client.initIndex(ALGOLIA_INDEX_NAME);
return index.saveObject(note);
});
To implement the search, the best way is to use instant search - android
Sample Search Image: GIF
The feature you're looking for is called full-text search and this is something most databases (including Firebase) don't provide out-of-the-box because it requires storing the data in a format that's optimized for text search (vs optimized for filtering) - these are two different problem sets with a different set of trade-offs.
So you would have to use a separate full-text search engine in conjunction with Firebase to be able to do this, especially if you need features like faceting, typo tolerance, merchandizing, etc.
You have a few options for a full-text search engine:
There's Algolia which is easy to get up and running but can get expensive quickly
There's ElasticSearch which has a steep learning curve but uber flexible
There's Typesense which aims to be an open source alternative to Algolia.
I don't know about the certainty of this approach but using the firebase version 10.2.6 on android, i get to do something like this:
firebaseDatabase.getReference("parent")
.orderByChild("childNode")
.startAt("[a-zA-Z0-9]*")
.endAt(searchString)
It seems to work well sometimes
Finally joined SO just to answer this.
For anyone coming here from/for the python firestore.client here's a solution that seems to work for me.
It's based on the accepted answer's concept but via the client rather than db.reference() and mixed with the answer from user12750908.
from firebase_admin import firestore
users = db.collection("users")\
.order_by("last_name")\
.where("last_name", ">=", last_name.upper())\
.where("last_name", "<=", last_name.lower() + "\uf8ff")\
.stream()
It works for the simple test I did, but I'll update my answer if I have issues with it later. And just a reminder, this is similar to
LIKE search%
and not
LIKE %search%.
Edit 1
I didn't see any tags for the question, but the title attribute mentions Android so this may not necessarily answer the question directly, but if you have a python API, this should work. I'm unfortunately not sure if there's an equivalent client/db separation in the Android version like there is in the Firebase Admin for Python. I didn't want to delete the answer since I hadn't seen any answers for firestore client during my search for a similar answer and hope it helps anyone else stumbling around.
Edit 09-03-2020 This works a portion of the time it seems. Most of the time I didn't seem to have an issue, but when I applied it to another project I was getting unexpected results. Long story short you may need to replicate how you save the data you're comparing against. For example, you may need to have a field to save the last_name in all caps and another field to save it in all lowercase, then you change the first where clause to compare last_name_upper and the second to compare last_name_lowercase. In my second project so far this seems to yield more accurate results so you may want to give that a try if the previous answer doesn't work well
EDIT 09-07-2020 Previous edit from 09-03-2020 is partially accurate. During my haste of thinking I had it fully resolved I completely forgot firebase doesn't let you use <, >, <=, >= across different fields. You may need to do two queries and merge them, but you'd probably still be reading more docs than you really intend. Doing the comparison against either the upper or lower version with the appropriate search term seems to give the original results expected from the original answer. For example:
.orderBy("last_name_upper")
.where("last_name_upper", ">=", this.searchForm.text.toUpperCase())
.where("last_name_upper", "<=", this.searchForm.text.toUpperCase() + "\uf8ff")
As firebase documentation, firebase doesn't support full text search.
But to do that you can use third-party tools.
Check this link to learn more https://firebase.google.com/docs/firestore/solutions/search

Android - how to create custom word dictionary for only my application?

I have successfully added a word to Android's predefined user dictionary, but i want to create a custom dictionary which can only be accessed by my application.
For example: When i type "lol", the suggestions show me "laugh out loud" but when I want another meaning of "lol" then I can manually add another meaning of "lol" (eg, "xxxxxx" - so the next time the user writes "lol" in an EditText, the suggestions will show him "xxxxxx").
No other application should have access my dictionary data.
I have worked with spell checker class but it gives me only correct word and I can't my own word meanings.
Please give me some suggestions or links.
There is an Androids inbuilt class UserDictionary so that you can add your spells programmatically into that, Here is a link you can go through with , and which may relates to your problem .(In this solution nidhi has manged programmatically to retrieve data back)
Add word to user dictionary and retrieve them back from dictionary
In addition you can go through following links to :
http://developer.android.com/reference/android/provider/UserDictionary.html
http://developer.android.com/reference/android/provider/UserDictionary.Words.html
Moreover if you want a custom personal dictionary then manually you have to store words and retrieve them back .
Hope that helps !!!

Android TextViews. Is parametrization possible? Is binding to model possible?

I am new to both Android and Stack Overflow. I have started developing and Android App and I am wondering two things:
1) Is it possible to parametrize a TextView? Lets say I want to render a text message which states something like: "The user age is 38". Lets suppose that the user age is the result of an algorithm. Using some typical i18n framework I would write in my i18n file something like "The user age is {0}". Then at run time I would populate parameters accordingly. I haven't been able to figure out how to do this or similar approach in Android.
2) Let's suppose I have a complex object with many fields. Eg: PersonModel which has id, name, age, country, favorite video game, whatever. If I want to render all this information into a single layout in one of my activities the only way I have found is getting all needed TextViews by id and then populate them one by one through code.
I was wondering if there is some mapping / binding mechanism in which I can execute something like: render(myPerson, myView) and that automatically through reflection each of the model properties get mapped into each of the TextViews.
If someone has ever worked with SpringMVC, Im looking for something similar to their mechanism to map domain objects / models to views (e.g. spring:forms).
Thanks a lot in advanced for your help. Hope this is useful for somebody else =)
bye!
In answer to #1: You want String.format(). It'll let you do something like:
int age = 38;
String ageMessage = "The user age is %d";
myTextView.setText(String.format(ageMessage, age));
The two you'll use the most are %d for numbers and %s for strings. It uses printf format if you know it, if you don't there's a quicky tutorial in the Formatter docs.
For #2 I think you're doing it the best way there is (grab view hooks and fill them in manually). If you come across anything else I'd love to see it.

Categories

Resources