I need a firebase query that is equivalent to this query in SQL:
select * from your_table where id in (123, 345, 679)
How would you do this logic in firebase?
thx,
Firebase's queries don't have an OR or IN operator. So you cannot easily map the above query to Firebase.
One workaround would be to implement a function that simply loops over the elements:
function loadThese(ids, callback) {
var rows = [];
while (ids.length > 0) {
var id = ids.splice(0,1)[0];
refToTable.child(id).once('value', function(snapshot) {
rows.push(snapshot.val());
});
}
callback(rows);
}
Note that the above should probably be recursive, so use it for inspiration and not as copy/paste code.
Another (and probably better way) to solve the problem is by figuring out why these three rows are selected and why not others. These rows probably have something in common. Once you know what they have in common, you can model that into the data structure.
Update (20160408): for a good explanation of why the above is a lot faster on Firebase than you might expect, see this answer.
Related
I'm currently working on pagination in DynamoDB using the JS AWS-SDK's executeStatement using PartiQL, but my returned object does not contain a NextToken (only the Items array), which is used to paginate.
This is what the code looks like (pretty simple):
const statement = `SELECT "user", "id" FROM "TABLE-X" WHERE "activity" = 'XXXX'`;
const params = {Statement: statement};
try {
const posted = await dynamodb.executeStatement(params).promise();
return { posted: posted };
} catch(err) {
throw new Error(err);
}
I was wondering if anyone has dealt with pagination using PartiQL for DynamoDB.
Could this be because my partition key is a string type?
Still trying to figure it out.
Thanks, in advance!
It turns out that if you want a NextToken DO NOT use version 2 of the AWS SDK for JavaScript. Use version 3. Version 3 will always return a NextToken, even if it is undefined.
From there you can figure out your limits, etc (default limit until you actually get a NextToken is 1MB). You'll need to look into the dynamodb v3 execute statement method.
You can also look into dynamodb paginators, which I've never used, but plan on studying.
Is there a simple way to modify this code to return only records where LocationID matches the id I'm trying to pass as a parameter? Needless to say, this doesn't compile. I thought Entity Framework was meant to make things easier, but I've searched online and can't find an understandable example of how to assign a simple query where a field in a single table/entity matches a number.
public async Task<List<PC>> GetPCsAsync(int id)
{
// Get our data. Don't yet know how to feed the variable to EF/Linq
PCList = await (from p in db.PC
select new PC {p.LocationID = id}).ToListAsync();
return PCList;
}
Thanks.
And also if you want to do it using Query Syntax it would be something like this:
PCList = await (from p in db.PC
where p.LocationID == id
select p).ToListAsync();
Here's a link to understand the differences between Query and Method syntax.
var list = db.PC.Where(x=>x.LocationID == id).ToList();
for async
var listAsync = await db.PC.Where(x=>x.LocationID == id).ToListAsync();
I hope it's help you!
Hi i have a noSql db in firebase.
I want to get the object where userId is 288
i'v tried many combinations but i cant figure out how its done.
This is my code so far :
var refTest= database.ref('conversation')
var query = refTest
.orderByChild('messages');
query.on('value', function(data) {
var a = data.val();
console.log(a.messages.userId);
console.log(data.val());
});
This is a image of my "schema"
I'm obviously a noob when it comes to NoSQL. I do understand SQL
All help is appreciated
You can order/filter on a nested value like this:
var refTest= database.ref('conversation')
var query = refTest.orderByChild('messages/userId').equalTo("288");
query.on('value', function(snapshot) {
snapshot.forEach(function(child) {
console.log(child.key);
console.log(child.val());
});
});
The forEach is needed, since there may be multiple child nodes with messages/userId equal to 288.
The key named "messages" doesn't make sense in your schema. Because if you want to have another message under that conversation, then you wouldn't be able to add it with the same key name and you also couldn't add it under "messages" because it would overwrite the other one. My suggestion is to use the push() method for adding a new message. This way you uniquely identify each message.
Regarding your question, an easy to understand way of parsing your schema is this: you loop through each message of each conversation for finding the messages with userID.
refTest.on('value', function(data) {
var conversations = data.val();
for (conversation in conversations){
for (message in conversation) {
if (message.userId == 288) {
// do whatever you need
// and eventually return something to break the loops
}
}
}
}
Of course, you can adapt it based on your needs
I want select from Firestore collection just articles written NOT by me.
Is it really so hard?
Every article has field "owner_uid".
Thats it: I JUST want to write equivalent to "select * from articles where uid<>request.auth.uid"
TL;DR: solution found already: usages for languages/platforms: https://firebase.google.com/docs/firestore/query-data/queries#kotlin+ktx_5
EDIT Sep 18 2020
The Firebase release notes suggest there are now not-in and != queries. (Proper documentation is now available.)
not-in finds documents where a specified field’s value is not in a specified array.
!= finds documents where a specified field's value does not equal the specified value.
Neither query operator will match documents where the specified field is not present. Be sure the see the documentation for the syntax for your language.
ORIGINAL ANSWER
Firestore doesn't provide inequality checks. According to the documentation:
The where() method takes three parameters: a field to filter on, a comparison operation, and a value. The comparison can be <, <=, ==, >, or >=.
Inequality operations don't scale like other operations that use an index. Firestore indexes are good for range queries. With this type of index, for an inequality query, the backend would still have to scan every document in the collection in order to come up with results, and that's extremely bad for performance when the number of documents grows large.
If you need to filter your results to remove particular items, you can still do that locally.
You also have the option of using multiple queries to exclude a distinct value. Something like this, if you want everything except 12. Query for value < 12, then query for value > 12, then merge the results in the client.
For android it should be easy implement with Task Api.
Newbie example:
FirebaseFirestore db = FirebaseFirestore.getInstance();
Query lessQuery = db.collection("users").whereLessThan("uid", currentUid);
Query greaterQuery = db.collection("users").whereGreaterThan("uid", currentUid);
Task lessQuery Task = firstQuery.get();
Task greaterQuery = secondQuery.get();
Task combinedTask = Tasks.whenAllSuccess(lessQuery , greaterQuery)
.addOnSuccessListener(new OnSuccessListener<List<Object>>() {
#Override
public void onSuccess(List<Object> list) {
//This is the list of "users" collection without user with currentUid
}
});
Also, with this you can combine any set of queries.
For web there is rxfire
This is an example of how I solved the problem in JavaScript:
let articlesToDisplay = await db
.collection('articles')
.get()
.then((snapshot) => {
let notMyArticles = snapshot.docs.filter( (article) =>
article.data().owner_uid !== request.auth.uid
)
return notMyArticles
})
It fetches all documents and uses Array.prototype.filter() to filter out the ones you don't want. This can be run server-side or client-side.
Updating the answer of Darren G, which caused "TypeError: Converting circular structure to JSON". When we perform the filter operation, the whole firebase object was added back to the array instead of just the data. We can solve this by chaining the filter method with the map method.
let articles = []
let articlesRefs = await db.collection('articles').get();
articles = articlesRefs.docs
.filter((article) => article.data.uid !== request.auth.uid) //Get Filtered Docs
.map((article) => article.data()); //Process Docs to Data
return articles
FYI: This is an expensive operation because you will fetching all the articles from database and then filtering them locallly.
Track all user id in a single document (or two)
filter unwanted id out
Use "where in"
var mylistofidwherenotme = // code to fetch the single document where you tracked all user id, then filter yourself out
database.collection("articles").where("blogId", "in", mylistofidwherenotme)
let query = docRef.where('role','>',user_role).where('role','<',user_role).get()
This is not functioning as the "not equal" operation in firestore with string values
You can filter the array of objects within the javascript code.
var data=[Object,Object,Object] // this is your object array
var newArray = data.filter(function(el) {
return el.gender != 'Male';
});
I need a firebase query that is equivalent to this query in SQL:
select * from your_table where id in (123, 345, 679)
How would you do this logic in firebase?
thx,
Firebase's queries don't have an OR or IN operator. So you cannot easily map the above query to Firebase.
One workaround would be to implement a function that simply loops over the elements:
function loadThese(ids, callback) {
var rows = [];
while (ids.length > 0) {
var id = ids.splice(0,1)[0];
refToTable.child(id).once('value', function(snapshot) {
rows.push(snapshot.val());
});
}
callback(rows);
}
Note that the above should probably be recursive, so use it for inspiration and not as copy/paste code.
Another (and probably better way) to solve the problem is by figuring out why these three rows are selected and why not others. These rows probably have something in common. Once you know what they have in common, you can model that into the data structure.
Update (20160408): for a good explanation of why the above is a lot faster on Firebase than you might expect, see this answer.