FlutterFlow: Sort collection of DocumentReference - firebase

I'm using the NoCode-app Flutterflow - and I need a piece of code ;) to sort a firestore-collection. I'm sure it can't be that hard, but I'm trying this for 2 days now...
I want the function to return a sorted list, based on a string-argument.
When I create a "custom function" (that's how a piece of code is called in FlutterFlow) I get this template:
import 'dart:math' as math;
List<DocumentReference> sortImages(
List<DocumentReference> listdocument,
String sortBy,
) {
return listdocument; '<<< what comes here? How do I sort?
}
How do I sort "sortImages" now by the argument "sortBy" and return it?
As you see I don't really have an idea of flutter/darts, and a NoSQL-db is also new to me... but I keep fighting to learn more every day!
Thanks a lot!

sorry if it's too late, but have you read this post?
How can I sort a list of strings in Dart?
There is a explanation of how to order string with different alternatives. This example should work in your custom function:
final List<String> fruits = <String>['bananas', 'apples', 'oranges'];
fruits.sort();
print(fruits);
Cheers!
Ariel-.

Related

Entity Framework query to return list with simple filter

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!

Ordering data does not actually order anything

I'm trying to get a dataset of messages out of my firebase database and want the messages sorted by added/timestamp. But for some reason no orderby I put in the code is actually used. I tried doing these 2 things.
_messagesRef = FirebaseDatabase.instance.reference().child('messages/'+key);
_membersSubscription = _messagesRef
.orderByChild('timestamp')
.onValue//On valuechange
.listen((Event event) => _messagesSubscriptionCallback(event));
_messagesRef = FirebaseDatabase.instance.reference().child('messages/'+key);
_membersSubscription = _messagesRef
.orderByKey()
.onValue//On valuechange
.listen((Event event) => _messagesSubscriptionCallback(event));
Both give me back the same dataset that is not ordered by timestamp or key in the callback. I've added the output underneath
{
-LA-Aw6crEAV53LxdujP:{
sender:1508,
message:test s9 2,
timestamp:1523642778089
},
-LA-Arby61T1UG5URMn6:{
sender:1508,
message:test s9,
timestamp:1523642759679
},
-LA-AyC7F8KAqceZBE3j:{
sender:1509,
message:test emu 1,
timestamp:1523642786632
},
-LA22WiUfL2tbh7-OjtM:{
sender:1508,
message:Blaj,
timestamp:1523690904480
},
-LA-B29RRXbdOPT1mG7m:{
sender:1508,
message:tesy3,
timestamp:1523642806940
}
}
This is how the data should be.
I hope someone can help me with this issue. I think I might misunderstand how ordering data works with Firebase
Kind regards,
Namanix
The result you show is a JSON object with other objects in there. JSON objects are never ordered as far as I know, only retrievable by key. JSON Arrays would be, but it doesn't look like you get that. When you would change this to an array the document IDs would have to be inside the document instead of being the object key. My guess would be that 'orderBy' is meant to be used for example to limit the number of items you get for pagination. Than you can order by timestamp, limit the number of items to 20 and search from the last timestamp you got.
I think if you want to order them I would put them in a new list of objects which can be ordered.
Most likely (it's hard to be sure without seeing _messagesSubscriptionCallback) you're throwing the ordering information away when you convert the data from Firebase into a plain JSON object, which (as Rene also says) doesn't have any defined order.
But the data your request from Firebase does have ordering information, you just have to be sure to not drop it.
The usual way to do this is to listen for onChildAdded instead of onValue. With that Firebase will invoke onChildAdded for each child in turn, and it will do so in the order you requested.
Also see this example and for example what FirebaseAnimatedList does here.
I now temporarily fixed it by doing this in my callback. But this feels like a very bad way to fix it. I hope to get some thoughts on this.
static void _messagesSubscriptionCallback(Event event) {
_messagesList.clear();
_messages.clear();
_messages = event.snapshot.value;
_messagesList = _messages.keys.toList();
_messagesList.sort((a, b) {
return b.compareTo(a) ;
});
onMessagesChange();
}

matteodem:meteor-easy-search - Is there a way to search only and exactly the first 4 characters

Is there a way to make it search only (and exactly) the first 3 or 4 characters of field?
For example say I have 3,000 postcode districts (in the UK). I am trying to search for "E14", currently the results include anything with E14 in it e.g.
====>Search results from query
DE14
E14 (===> what I actually want)
LE14
ME14
PE14
SE14
============
I'm thinking I could add something to the createSearchIndex code:
EasySearch.createSearchIndex('postcodeDistricts', {
'collection' : PostcodeDistricts,
'field' : 'postcodeDistrict',
'limit' : 8
});
One of the easy search package developers here. I know this question has already been resolved on Github, but I've actually seen this come up multiple times before, so maybe it'll help if I clarify some things here.
If you're not relying on elastic search, by default the package uses the mongo searcher. What this searcher does is look up documents with a regex like this:
{ '$regex' : '.*' + searchString + '.*', '$options' : 'i' }
With the query option, you have the option to effectively alter the regex passed into the query. So, changing the regex to something like '^' + searchString ends up matching all results with the content of searchString explicitly at the beginning, which is what OP wanted.
Hopefully we'll make this easier to do in the future, but for now that will work. Cheers :)
Had a response on the Github page to this, for anyone else that may be interested:
https://github.com/matteodem/meteor-easy-search/issues/95
====== UPDATED FOLLOWING COMMENTS REGARDING POSTING THE SOLUTION:
Solution for me was to include a query as follows
EasySearch.createSearchIndex('collectionName', {
'collection': CollectionName,
'field': 'fieldName', //What you'd like to query
'limit': 8 //Default is 10,
//A query is what is required. The below worked for me
'query': function (searchString, opts) {
var query = EasySearch.getSearch(this.use).defaultQuery(this, '^'+searchString);
return query;
}
})

Meteor.js: Find all documents and return in reverse natural order

I am trying to return all documents in a collection, to use it with an {{#each}} in my template. My code looks like this:
return Answers.find({}, {sort: {$natural:-1}})
But the documents are returned in natural order (not reverse). Does anyone know why? I got the $natural selector from the MongoDB documentation, so I don't see what's wrong.
Can't tell why don't it returns in reverse order.
But you can create an array in the template helper method and return reverse of an array using array.sort() or array.reverse() functions.
For ex: Say you Answers collection looks like this:
Answers({ansNo: 1, ansBody: "body1"},
{ansNo: 2, ansBody: "body2"},
{ansNo: 3, ansBody: "body3"});
And the array to be returned is:
var AnswersArr = new Array();
then in your template helper :->
var tempCollection = Answers.find({});
tempCollection.forEach(function(data){
var obj = {ansNo: data.asnNo, ansBody: data.ansBody};
AnswersArr.push(abj);
});
AnswersArr.sort(function(a, b){return b.ansNo - a.ansNo;}); //sort in reverse order
return AnswersArr;
Sort isn't a parameter but a separate function to be called after find() on the resulting Cursor object. This is the method that the MongoDB documentation is referring to and works with drivers such as MongoJS:
return Answers.find().sort({$natural: -1});
It seems Meteor hasn't added the sort() function to their implementation of Cursor, so an alternate solution would be to sort by the _id field which is generated based on date (and hence insertion order):
return Answers.find({}, {sort: {'_id': -1}});
As a workaround you could do this:
return Answers.find().fetch().reverse();
I know it would be nicer to do it via the sort parameter, but I don't think it's possible right now.
I think you might be confusing definitions of 'natural order' here. One the one hand there is a natural sort order for letters/strings (A,B,C...) and numbers (1,2,3...).
But in the case of mongo, 'natural' refers to the order the data was written to disk. '{$natural:1}' returns 'documents in the order they exist on disk...' and, so '{$natural:-1}' reverses that (http://docs.mongodb.org/manual/reference/operator/meta/natural/).
So without the code that writes the data and some insight into how it was written to disk, we cannot test your hypothesis that it is not working correctly.

Filter Products in a Dynamic Way using LINQ

After hours of trying and searching, I think its time to share my problem with you right now.
Problem Definition :
I have a Dictionary of KeyValuePairs(named filterPool) which includes an integer (PropertyID) and a string(McValue). What I am trying to do is filtering products depending on those KeyValuePairs and return them as a DataTable/List.
You may consider this as building dynamic "Where ... And .." clauses as SQL.
Here is the code that I am using :
foreach (KeyValuePair<int, string> filter in filterPool)
{
products = products.Where(i => i.PROPERTYID == filter.Key && i.MCVALUE.Equals(filter.Value));
}
return products.ToDataTable();
The problem is the foreach loop above seems to work only once, for the latest KeyValuePair available in the Dictionary.
As far as I could find on Stackoverflow, the closest solution to my problem was : this one, also using a Dictionary of values for filtering
There must be a way to achieve the goal of filtering using Dictionary and LINQ; or there's a huge thing that I am missing/ignoring to see somehow.
Hope the problem given is clear enough for all,
Thanks
^^
This is a closure issue. You can solve it by making a temporary:
foreach (KeyValuePair<int, string> filterTmp in filterPool)
{
var filter = filterTmp; // Make a temporary
products = products.Where(i => i.PROPERTYID == filter.Key && i.MCVALUE.Equals(filter.Value));
}
return products.ToDataTable();
For details on what's happening, see Eric Lippert's post Closing over the loop variable considered harmful.
Also note that this behavior has changed for C# 5. In C# 5/VS2012, this code would work as expected.
You're overwriting your products collection on every iteration of your foreach. I'm not sure what the data type on your collection is, but you'll want to do something like this in your foreach instead:
products.AddRange(products.Where(i => i.PROPERTYID == filter.Key && i.MCVALUE.Equals(filter.Value)));
I'm not sure if that makes sense, but it seems like you're trying to create a collection full of products that match your filterPool.
I think that it's better solved with aggregate:
return filter
.Aggregate(products, (acc, filter) => acc.Where(i => i.PROPERTYID == filter.Key && i.MCVALUE.Equals(filter.Value)));
.ToDataTable();

Resources