Is it possible to use a like/contains query in mLab?
I have json data like so on the server https://mlab.com/:
"County": "Kildare, Laois, Carlow"
I can query the dataset to return all where trails = County Kildare:
#GET("databases/walks/collections/walks")
Call<List<Trail>> byCounty (#Query("q") String county,#Query("apiKey") String apiKey);
The parameter "q" contains: q={"County": "Kildare"}
But that only select data that match the following :
"County": "Kildare"
Is there an Mlab query that has the same function as Contains in MongoDB or Like in SQL. So i can search the county field if it contains "Kildare".
Or even how to do it in A HTTP request, i might be able to use it within the q={ }.
Ive tried using q={"County":"/.*Kildare.*/"}
Thank You.
The q parameter in the mLab Data API is just a MongoDB query document. You can use any MongoDB operator like you would normally in a MongoDB query document.
MongoDB doesn't have a $contains operator. But if you're searching for text in a string, you can use the $regex or $text operator. See the documentation for $regex and the documentation for $text to learn more.
To use $regex, try this as the q parameter:
q={"County": {"$regex": "Kildare"}}
To use $text, first build a text index on the County field. You can do this on the mLab management portal (instructions in the documentation) or run this command on the mongo shell:
db.walks.createIndex({ County: "text" })
You can then try this as the q parameter:
q={"$text": {"$search": "Kildare"}}
Important Note: $regex and $text can be extremely inefficient operations. It may be much more efficient and easier for you to restructure your data model. Rather than having a list of counties in a string, perhaps have them in an array like so:
"County": ["Kildare", "Laois", "Carlow"]
Then to search for all documents that contain Kildare in their County array, you can simply use this query:
q={"County": "Kildare"}
This may be a better option for you than using $regex or $text.
Related
I'm using a Firebase Firestore for android to store data. I tried to search data from documents.
My Firestore structure is:
Collection (Products) - Document (Auto Generated ID) - Field (NumberOfPeople,OfferStartDate,OfferEndDate,OfferPrice,Location)
I wrote query for search data on those fields.
CollectionReference collectionOfProducts = db.collection("Products");
collectionOfProducts
.whereEqualTo("Location", location)
.whereGreaterThanOrEqualTo("OfferPrice", offerPrice)
.whereLessThanOrEqualTo("OfferPrice", offerPrice)
.whereGreaterThanOrEqualTo("OfferStartDate", date)
.whereLessThanOrEqualTo("OfferEndDate", date)
.get()
I want search result like this: An offer which is between start date and end date, where offer price is greater than equal or less than equal on give price range. This query is not working in android studio.
How to do this in firestore firebase?
According to the official documentation regarding Cloud Firestore queries, please note that there some query limitations:
In a compound query, range (<, <=, >, >=) and not equals (!=, not-in) comparisons must all filter on the same field.
So a Query object that contains a call to both methods:
.whereGreaterThanOrEqualTo("OfferStartDate", date)
.whereLessThanOrEqualTo("OfferEndDate", date)
Is actually not possible, as "OfferStartDate" and "OfferEndDate" are different properties.
The best solution I can think of is to use only one of these method calls and do the other filtering on the client.
Another possible solution might be to use denormalization and duplicate the data
in certain intervals. In this way, you'll always know the time periods and you'll be able to create the corresponding queries.
To the best of my knowledge, Firestore only lets you use where<Greater/Less>ThanOrEqualTo() and where<Greater/Less>Than() a single field and all other filter operations on other fields can only be whereEqualTo().
Some workarounds for your specific case include -
1) Modifying your query to
collectionOfProducts
.whereGreaterThanOrEqualTo("OfferStartDate", date)
.whereEqualTo("Location", location)
.get()
And then performing the subsequent filtering on the result in your app code.
Alternately, you can perform your filter on "OfferPrice" and "Location" in your query and the remaining filters can be applied to the query result.
2) You can use firebase functions or other server code to write logic that performs customized filtering and fetch the result that way.
i was having same issue with this, but i found a work around that takes sometime to write.
lets say you want to search for a particular keyword(in this case the value of a field inside a document), and you want firebase to search multiple field instead of just looking for 1 particular field.
this is what you want to do.
const searchTerm = document.createElement('input')
db.collection('collection').where('field1', '==', `${searchTerm.value}`)
.get()
.then((snapshot) => {
if(snapshot.size === '0'){
db.collection('collection').where('field2', '==', `${searchTerm.value}`)
.get()
.then((snapshot) => {
if(snapshot.size === 0) {
db.collection......and repeat
}
})
}
})
in summary, the above code is basically telling js to search for the term again with a different field if the result of the previous query is 0. I know this solution might not be able to work if we have a large quantity of fields. But for folks out there that are working with small number fields, this solution might be able to help.
I really do hope firestore one day would allow such feature, but here is the code it worked fine for me.
the problem I have now is to allow search input to be able to search without have me to complete the word. I do currently have an idea how this would be, but just need some time to put together.
I'm no back-end developer. So perspective is always appreciated.
I have written a script which requests from an API and creates this huge JSON file I want to save in firebase, how can I accomplish this? And would it be possible to filter this json with python for example; when I add region=eu in the url this returns the objects which have Europe as region or do I absolutely need to request the entire json file and parse in my code (java android) ?
Since there are a few parts to your question:
You can save JSON to Firebase and the data will be mapped to child locations:
Using PUT, we can write a string, number, boolean, array or any JSON object to our Firebase database...When a JSON object is saved to the database, the object properties are automatically mapped to child locations in a nested fashion.
https://firebase.google.com/docs/database/rest/save-data
And for your next question:
And would it be possible to filter this json with python for example; when I add region=eu in the url this returns the objects which have Europe as region
Looks like you should be able to jimmy something together with Firebase's filters, startAt and endAt:
We can combine startAt and endAt to limit both ends of our query.
https://firebase.google.com/docs/database/rest/retrieve-data#section-rest-filtering
For your example you might do something like this:
curl 'https://yourfirebase.firebaseio.com/yourendpoint.json?orderBy="$REGION_NAME"&startAt="EU"&endAt="EU"&print=pretty'
...or do I absolutely need to request the entire json file and parse in my code (java android) ?
The facts that JSON objects are stored hierarchically in Firebase and that you can filter based on those object values makes me think you do not, in fact, have to request the entire JSON file. However, I don't have personal experience with this particular aspect of Firebase, so give it a shot!
As #ackushiw mentions in the comments, you can also use the equalTo query (https://firebase.google.com/docs/reference/js/firebase.database.Query#equalTo):
curl 'https://yourfirebase.firebaseio.com/yourendpoint.json?orderBy="$REGION_NAME"&equalTo="EU"&print=pretty'
It really depends on how you are structuring your JSON. It's generally recommended to make your JSON tree as shallow as possible since all children are loaded when you have a matching query.
FIREBASE DATA:
{
"-id1": {
"region": "eu" // bear in mind queries are case sensitive
"title": "Foo"
"nested": {
"city": "berlin"
}
},
"-id2": {
"region": "other"
"title": "Bar"
"nested": {
"city": "berlin"
}
},
"-id3": {
"region": "eu"
"title": "Baz"
"nested": {
"city": "paris"
}
}
}
Querying with (using the Android API)
.orderByChild("region").equalTo("eu")
would return "-id1" and "-id3"
with
.orderByChild("nested/city").equalTo("berlin")
would return "-id1" and "-id2"
The REST API Returns Unsorted Results: JSON interpreters do not enforce any ordering on the result set. While orderBy can be used in combination with startAt, endAt, limitToFirst, or limitToLast to return a subset of the data, the returned results will not be sorted. Therefore, it may be necessary to manually sort the results if ordering is important.
If you're using a more complex structure I recommend watching this video
https://www.youtube.com/watch?v=vKqXSZLLnHA
I'd also recommend using the firebase library for Android
https://firebase.google.com/docs/android/setup
And Firebase-UI, It does a lot for you.
https://firebaseopensource.com/projects/firebase/firebaseui-android/
If there is a String named 'California' at firestore database and i want to search from android app as 'Cali' then the firebase should return me California.
How can i do that query?
There has some function at firestore like,
db.collection("cities").whereEqualTo("name", "Cali")
db.collection("cities").whereLessThan("name", "Cali")
db.collection("cities").whereGreaterThanOrEqualTo("name", "Cali")
db.collection("cities").whereGreaterThan("name", "Cali")
db.collection("cities").whereGreaterThanOrEqualTo("name", "Cali")
But i need a function like as,
db.collection("cities").whereContain("name", "Cali")
which should return full string that contains 'Cali' substring.
Unfortunately, there is no query in Firestore that looks like this:
db.collection("cities").whereContains("name", "Cali")
But for small datasets, there is a workaround that can help you solve this, which is by querying the database to get all city names and use contains() method like this:
String str1 = document.getString("yourProperty");
String str2 = "Cali";
boolean b = str1.toLowerCase().contains(str2.toLowerCase());
If you'll try to print the value of b, you'll see that is true. But the above examples works well enough only for small datasets, it doesn't work for large datasets and this is because downloading an entire collection to search for fields client-side isn't practical. In this case, as the official documentation recommends:
To enable full text search of your Cloud Firestore data, use a third-party search service like Algolia.
For a concrete example, please also see my answer from this post.
I have ran the android version of bluelist tutorial in bluemix.
This app saves data as key-value. For example firstname:.
What if i want to store last name too? Can i create a second "column" or should i make my "person" object a json string and store it?
Check out the tutorial here (http://mbaas-gettingstarted.ng.bluemix.net/android). You can store a Java object in the mobile data service. Behind the scenes it is storing JSON for you. If you want you can obviously store straight JSON but it was abstracted a bit so it models more closley how Java dev's use OO to store and access data.
Scroll down to the data operations bit (http://mbaas-gettingstarted.ng.bluemix.net/android#data-operations), you can store and access data normally as you would through a class in Java.
What i have done eventually is that i stored a json string like
{"firstname":"John","lastname":"Foo"}
In the bluelist application i maintain 2 Lists, one for the whole object and one for the fistsnames only.
By this way i see only the firstname but i can store more than one properties.
(of course as there is one editbox i can set and edit only one property. The second property is a static string - eg it is always John - but i just wanted to test the functionality of the key-value database so it is ok for me.)
This is the accepted answer so far. If there is any other way please answer with an example as i am not too much familiar with this kind of database.
if its a web application,you can use similar logic like below:
var newUser = {
'username': $('#addUser fieldset input#inputUserName').val(),
'email': $('#addUser fieldset input#inputUserEmail').val(),
'fullname': $('#addUser fieldset input#inputUserFullname').val(),
'age': $('#addUser fieldset input#inputUserAge').val(),
'location': $('#addUser fieldset input#inputUserLocation').val(),
'gender': $('#addUser fieldset input#inputUserGender').val()
}
// Use AJAX to post the object to our adduser service
$.ajax({
type: 'POST',
data: newUser,
url: '/users/adduser',
dataType: 'JSON'
}).done(function( response )
You can follow below link for more details on how to add new column and doing insert/update/delete operation on this:
http://cwbuecheler.com/web/tutorials/2014/restful-web-app-node-express-mongodb/
I am using PHP as a middleman to access a MySql database and it returns the result of the query as a json string using json_encode, then display it within the TableLayout of the app, this is why order is important so I can line up the data and the headers.
After some research I found out that json does not enforce order so any time I call new JSONArray(result) it scrambles the json returned by PHP. Is there any way to preserve the order of the returned string? Or maybe I'm using the incorrect data structure on either end.
Relevant PHP result:
[{"FIELD1":"vsa","FIELD2":"dfs","FIELD3":"dsfa","FIELD4":"adsf","FIELD5":"23","ZIPCODE":"asdf","USERNAME":"asd","PASSWORD":"as","DATE1":"dsfa"}]
Relevant Android Result After JSONArray(result):
[{"ZIPCODE":"asdf","DATE1":"dsfa","FIELD3":"dsfa","FIELD2":"dfs","FIELD5":"23","FIELD4":"adsf","USERNAME":"asd","FIELD1":"vsa","PASSWORD":"as"}]
I believe the reordering inside a JSON object is due to the fact that JSON objects are key/value pairs (not an indexed array), which by default are unordered. However, the JSON array is an ordered sequence of values (JSON objects).
Don't rely on order!
Source: http://www.ietf.org/rfc/rfc4627.txt
I've never seen new JSONArray(String) change the order of anything, and I've used it a lot. However, what you have seems to be an array of length 1. Using myJsonArray.getJsonObject(0).getString("ZIPCODE") should still return the correct data, and as long as you query in the correct order (FIELD1, FIELD2, FIELD3, etc), you should be fine.