I'm making a social media app like instagram, but trying to filter out the user's own posts so they don't see it on their feed. I'm trying to do it like below, but it causes the app to crash. When I change it to .whereEqualTo, it works just fine and only shows posts by the users. As far as I know, the two should work exactly the same, with the obvious exception of it being equal to vs not, so why does one work but the other doesn't?
Does not work
Query query = firestoreDb.collection("posts")
.whereNotEqualTo("user.username", username)
Shows only posts by users
Query query = firestoreDb.collection("posts")
.whereEqualTo("user.username", username)
The error I get is
You have an inequality where filter (whereLessThan(), whereGreaterThan(), etc.) on field 'user.username' and so you must also have 'user.username' as your first orderBy() field, but your first orderBy() is currently on field 'creationTime' instead
but I don't want to order by username.
If you want to use an inequality filter (such as whereNotEqualTo) in your query, you are obliged to order the results by the field on that filter. That is a hard requirement of Firestore, due to the way it's organized. The only way to work around that is to reorder the query results in your app code - you will not be able to coerce the query to do what you want.
See also:
Firestore "Invalid query" - Am I using Indexing wrong?
Firestore query order on field with filter on a different field
Related
I have a Quarkus application where we use Hibernate ORM with Panache to build and query the database. In some situations, we want to use an List or rather a Set to filter from a table of "requests". The Request entity, which has a different name in practice, has a status property, which is an enum that can have three values: PENDING, APPROVED or DENIED. In the web front-end, we want to use a checkbox-style filter which then during the HTTP request sends this as an array to the Quarkus application, where we then want to give it to Hibernate somehow, preferably as a Set to easily filter duplicates.
I've done something extremely similar within the NodeJS/MongoDB ecosystem in the past, which looks like this, as a step of a bigger aggregate pipeline:
aggregatePipeline.push({
$match: {
status: {
$ne: status //Array of strings
}
}
});
How would something like this be done within Hibernate? I've tried some googling, but the results are largely cluttered by people asking how you get an Arraylist out of the cursor from a standard find-query.
Thanks in advance.
Edit: Trying this line
List<Publisher> publishers = Publisher.find("name", Arrays.asList("Books", "Publishing")).list();
Gives this error:
org.postgresql.util.PSQLException: ERROR: operator does not exist: character varying = record
Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
Nevermind. I tried thinking about another search term which wouldn't result in a flood of irrelevant results I mentioned. I tried "Hibernate find in set", which led me to find this other post. This led me to try this line (with the Set values hardcoded for FAAFO purposes):
List<Publisher> publishers = Publisher.find("name IN ?1", new HashSet<>(Arrays.asList("Indiana University Press", "Harvard University Press"))).list();
No errors, and returns two entries that were imported into the dev db through the import.sql file. It's the "IN ?1" part that does it, not that I used a Set for my query instead of a List this time. It works just as well with a List, as long as the "IN ?1" stays there.
I have an Saleforce app that allows me to execute REST API calls, and I need to retrieve orders (/services/data/v47.0/sobjects/Order) by status.
I've found some manual that describes similar filtering on another entitiy (https://developer.salesforce.com/docs/atlas.en-us.api_placeorder.meta/api_placeorder/sforce_placeorder_rest_api_standalone.htm).
However when trying to execute followin request, it seems that all statuses returned:
GET /services/data/v47.0/sobjects/Order?order.status='ddd'
I also tried some variations of query params. Is this functionality supported?
/sobjects service will let you learn dynamically what fields (standard and custom) exist in Order table (or any other really), what types they are, picklist values...
To retrieve actual data you can use query resource. (Salesforce uses a dialect of SQL, called SOQL. If you've never used it before it'll look bit weird the moment you want to do any JOINs, would be nice if a SF developer would fill you in)
This might be a good start
/services/data/v47.0/query/?q=SELECT Id, Name, OrderNumber FROM Order WHERE Status = 'Draft' LIMIT 10
Never seen the API you've linked to, interesting stuff. But I don't see anything obvious that would let you filter by status there so the more generic "query anything you wish" might work better for you. Play a bit and perhaps https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_query.htm will suit your needs more?
I need to filter the list of my documents which I am fetching from firestore in my android app. this is the query.
query = FirebaseFirestore.getInstance()
.collection("students")
.whereLessThan("mAge",25)
.whereGreaterThan("mAge",20)
.whereGreaterThan("mGrades",20);
but, I get an error in the log:
java.lang.RuntimeException: Unable to start activity ComponentInfo{dsardy.in.acchebacche/dsardy.in.acchebacche.MainActivity}: java.lang.IllegalArgumentException: All where filters other than whereEqualTo() must be on the same field. But you have filters on 'mAge' and 'mGrades'
Can this be achieved? a filter with two or more fields greater than some values is an important and general query, firestore must have something to tackle this.
Firestore allows to chain multiple where() methods to create more specific queries but only on the same field. As you can probably see in the official documentation range filters on different fields are forbidden.
To achieve what you want, you need to query your database twice, once to fiter data using .whereGreaterThan("mAge",20) and second using .whereGreaterThan("mGrades",20) but you cannot use them in the same query.
Another way to make it happen is to store a special field that might fit the query, although in real world applications it will almost impossible to store every single way a user might query the data.
My situation is that, given 3 following methods (I used couchbase-java-client 2.2 in Scala. And Version of Couchbase server is 4.1):
def findAll() = {
bucket.query(N1qlQuery.simple(select("*").from(i(DatabaseBucket.USER))))
.allRows().toList
}
def findById(id: UUID) = {
Option(bucket.get(id.toString, classOf[RawJsonDocument])).map(i => read[User](i.content()))
}
def upsert(i: User) = {
bucket.async().upsert(RawJsonDocument.create(i.id.toString, write(i)))
}
Basically, they are insert, find one by id and findAll. I did an experiment where :
I insert a User, then find one by findById right after that, I got a user that I have inserted correctly.
I insert and then I use findAll right after that, it returns empty.
I insert, put 3 seconds delay and then I use findAll, I can find the one that I have inserted.
By that, I suspected that N1qlQuery only search over cached layer rather than "persist" layer. So, how can I force to let it search on "persist" layer?
In Couchbase 4.0 with N1QL, there are different consistency levels you can specify when querying which correspond to different cost for updates/changes to propagate through index recalculation. These aren't tied to whether or not data is persisted, but rather it's an option when you issue the query. The default is "not bounded" and to make sure that your upsert request is taken into consideration, you'll want to issue this query as "request plus".
To get the effect you're looking for, you'll want to add N1qlPararms on your creation of the N1qlQuery by using another form of the simple() method. Add a N1qlParams with ScanConsistency.REQUEST_PLUS. You can read more about this in Couchbase's Developer Guide. There's a Java API example of this. With that change, you won't need to have a sleep() in there, the system will automatically service the query request once the index recalculation has gotten to your specified level.
Depending on how you're using this elsewhere in your application, there are times you may want either consistency level.
You need stronger scan consistency. Add a N1qlParam to the query, using consistency(ScanConsistency.REQUEST_PLUS)
We are wanting to create a Facebook application that people can add to their page, and then when they post content from it on their wall, we want to have the ability for our application to periodically query for posts created by use of this application to pull and display back on our website. I've perused the documentation and don't see a way, so figured I'd ask incase I'm just missing it.
Thank you,
JT
Here is some thoughts that maybe will steer you in the right direction (I haven't tried this myself).
You can get wall posts by running FQL on stream table. Getting all wall posts by user id (source_id) seems straight forward, but getting all wall posts made from an app might require some extra work. Doc says:
If you want to return all the posts from a user's stream that were published through your application, make sure you include the app_id in your query.
Not sure if query will work if you do a search directly by app_id field as it is not indexed (but worth trying). If not, then looks like you need to do a search by filter_key. Now docs don't really explain what exactly that field means (surprise), but on their stream.get page from Old REST API it says:
You can determine the filters using stream.getFilters or querying the stream_filter FQL table. Filters can be user-defined, Facebook-defined (like News Feed/nf or networks), or for applications (app_<APPLICATION ID>).
Looks like app_<APPLICATION ID> filter is what we need for filter_key field (if that still works). If not then play with stream_filter table and see what kind of filters it contains and if there any sort of app filter available. I suspect your FQL might look something like:
SELECT message FROM stream WHERE filter_key = "application" AND app_id = 123456789