How to deal with indexes of multiple where query in firebase? - database

In my flutter app. I have to fetch data from firebase using multiple filters.
I've done as below. It worked but the problem is that some filter is null so I need to skip it in the firebase query, therefore, even I have only 2 fields (name, age) I have to create 3 indexes for supporting my query. 1st index is for: name, 2nd index is for: age, 3rd index is for: name and age.
Future<List<Transac>> getTrans(TransFilter filter, Transac? lastTrans) async {
const limit = 10;
var result =
_collection.orderBy(filter.orderBy, descending: true).limit(limit);
if (filter.directionId != null) {
result = result.where(directionIdKey, isEqualTo: filter.directionId);
}
if (filter.flag != null) {
result = result.where(Transac.flagKey, isEqualTo: filter.flag);
}
if (filter.officeId != null) {
result = result.where(officeIdKey, isEqualTo: filter.officeId);
}
if (lastTrans != null) {
result = result.startAfter([lastTrans.createdAt.millisecondsSinceEpoch]);
}
final _result = await result.get().then(
(value) => value.docs.map((e) => Transac.fromSnapshot(e)).toList());
return _result;
}
I have tried something as below because I think I just need to create all indexs at once, but it throws an error because I cannot use isNotEqualTo on the field that not use in the first orderby.
Future<List<Transac>> getTrans(TransFilter filter, Transac? lastTrans) async {
const limit = 10;
var result =
_collection.orderBy(filter.orderBy, descending: true).limit(limit);
if (filter.directionId != null) {
result = result.where(directionIdKey, isEqualTo: filter.directionId);
}else {
result = result.where(directionIdKey, isNotEqualTo: '');
}
if (filter.officeId != null) {
result = result.where(officeIdKey, isEqualTo: filter.officeId);
}else {
result = result.where(officeIdKey, isNotEqualTo: '');
}
if (lastTrans != null) {
result = result.startAfter([lastTrans.createdAt.millisecondsSinceEpoch]);
}
final _result = await result.get().then(
(value) => value.docs.map((e) => Transac.fromSnapshot(e)).toList());
return _result;
}
Any solution or suggestion? Your help will be much appreciated, Thank you

You have 3 parameters that you want to filterBy directionIdKey, Transac.flagKey, officeIdKey. You want to orderBy: filter.orderBy.
I believe these parameters are holding the field names.
We need a field that will be present in all queries. We use your orderBy field.
So create 3 composite indexes.
filter.orderBy and directionIdKey ASC
filter.orderBy and Transac.flagKey ASC
filter.orderBy and officeIdKey ASC
This should handle your queries.

Related

firestore order by descending breaks when using startAfter

I have a function here that is being used to fetch all the documents in a collection.
The information returned is paginated and will only return the next documents when the user scrolls down the page.
export function fetchScreamsFromFirestore(limit, lastDocSnapshot = null) {
let screamsRef = db
.collection('screams')
.orderBy('createdAt')
.startAfter(lastDocSnapshot)
.limit(limit);
return screamsRef;
}
When I add the 'desc' argument to this function like so:
export function fetchScreamsFromFirestore(limit, lastDocSnapshot = null) {
let screamsRef = db
.collection('screams')
.orderBy('createdAt', 'desc')
.startAfter(lastDocSnapshot)
.limit(limit);
return screamsRef;
}
It then returns nothing. Any thought on how I can fix this?
I am a little late here but I think this might just be a syntax issue?
Try...
export function fetchScreamsFromFirestore(limit, lastDocSnapshot = null) {
let screamsRef = db
.collection('screams')
.orderBy('createdAt', descending: true)
.startAfter(lastDocSnapshot)
.limit(limit);
return screamsRef;
}

How to filter array angular

I have an array containing guidelines. Using a query I want to filter this array using only the guidelines that contains (part of) the query. I have the following code.
filterguideline() {
const query = this.recommendationForm.get('guideline').value;
if (query !== "") {
this.filteredguidelineList = this.Guidelines.filter(function (el) {
return el.toLowerCase().indexOf(this.query.toLowerCase()) > -1;
}.bind(this));
} else {
this.filteredguidelineList = [];
}
}
This does not really work. It does not filter the array, but simply shows all the values in the Guidelines array (irrespective of what the query contains).
Does anybody know the solution?
You need to use arrow function or like below,
if (query !== "") {
this.filteredguidelineList = this.Guidelines.filter(t=>t.toLowerCase().indexOf(this.query.toLowerCase()) > -1);
} else {
this.filteredguidelineList = [];
}
return this.filteredguidelineList;
Using arrow function,
this.filteredguidelineList = this.Guidelines.filter((el) => {
return el.toLowerCase().indexOf(this.query.toLowerCase()) > -1;
});

Filter Firestore with multiple where not working

I have this docs
let wall = firebase.wallCollection;
then I want to filter it with multiple where:
location (location == filterLocation)
price (price < filterMaximumPrice)
This is my filter methods on Vue
filterResult(){
let self = this;
if(self.filterLocation!=""){
wall.where('location','==', self.filterLocation);
console.log("Location flag");
}
if(parseInt(self.filterMaximumPrice)!=0){
dinding.where('price','<', parseInt(self.filterMaximumPrice));
console.log("Price flag");
}
wall.get()
.then(snapshots => {
snapshots.forEach(doc => {
self.listFilteredWall.push(doc.data());
}, this);
})
}
The problem is that 2 where function not working and still give all wall output without filter.
How to fix this?
CollectionReference extends Query. The result of where() is a new Query:
Creates a new query that returns only documents that include the
specified fields and where the values satisfy the constraints
provided.
You need to retain the result Query if each where() and use it for the get(). Something like this:
filterResult(){
let self = this;
let query = wall;
if(self.filterLocation!=""){
query = query.where('location','==', self.filterLocation);
console.log("Location flag");
}
if(parseInt(self.filterMaximumPrice)!=0){
query = query.where('price','<', parseInt(self.filterMaximumPrice));
console.log("Price flag");
}
query.get()
.then(snapshots => {
snapshots.forEach(doc => {
self.listFilteredWall.push(doc.data());
}, this);
})
}

how to filter data from store in extJS?

Please see bellow code, that I use for filtering data.
listeners: {
keyup: function (e, t, eOpts) {
var text = e.getValue();
var s = Ext.getStore('TempSensorDetailsStore');
s.clearFilter();
if (text) {
s.filterBy(function (rec) {
var str = (rec.get('vehicleNo')).toLowerCase();
var res = str.indexOf(text.toLowerCase());
if (res == 0) {
return true;
}
});
} else {
s.clearFilter();
}
}
}
Above code get filter the data, But not as per my expectations,
Search Result showing record which is matching the first letter of vehicle Number only...it should return the vehicle No if that character is present in Vehicle no
For Example.
Vehicle No.Abc-37046 and if user search 37046 then also it returns vehicle
I got Solution,
There was just need to change code
if (res >- 1)
Instead of
if (res == 0)

Sitecore doesn't remove records from custom solr index

I have strange issue when I am trying to remove some records from custom solr index.
I created code like this
public void DeleteRecordsFromIndex(string indexName,IEnumerable<IIndexableUniqueId> uniqueIds)
{
if (uniqueIds == null || string.IsNullOrEmpty(indexName) || !uniqueIds.Any())
{
return;
}
using (IProviderDeleteContext deleteContext = ContentSearchManager.GetIndex(indexName).CreateDeleteContext())
{
foreach (var indexId in uniqueIds)
{
deleteContext.Delete(indexId);
}
deleteContext.Commit();
}
}
Search Item property when I need to get UniqueId
[IndexField("_uniqueid")]
public IIndexableUniqueId UniqueId
{
get
{
return new `enter code here`IndexableUniqueId<string>(this.Uri.ToString());
}
}
Based on debug info IIndexableUniqueId contains correct values
like:"sitecore://web/{66d75448-72a5-4d94-9788-61c6c64b9251}?lang=en-au&ver=1"
what is equal to _uniqueid field in solr index.
I had 4 records in my custom solr index.
After first run one records was removed from index, But 3 records are steel there.
I have ran code couple of times, but 3 records always inside of index.
What could be wrong with my code ?
I found solution:
insted of using IIndexableUniqueId it is better to use IIndexableId
public IIndexableId GetIndexableId(ID itemId)
{
//map to _group value
var id = itemId.ToString().ToLower().Replace("{", "").Replace("}", "").Replace("-", "");
return new IndexableId<string>(id);
}
public int DeleteRecordsFromIndex(string indexName, IIndexableId uniqueIds)
{
if (uniqueIds == null || string.IsNullOrEmpty(indexName))
{
return -1;
}
using (var deleteContext = ContentSearchManager.GetIndex(indexName).CreateDeleteContext())
{
var resuls = deleteContext.Delete(uniqueIds);//this method use _group fields for remove records. All languages will be removed.
deleteContext.Commit();
return resuls;
}
}
regarding ILSpy, sitecore remove item by _group
// Sitecore.ContentSearch.SolrProvider.SolrUpdateContext
public void Delete(IIndexableId id)
{
Assert.ArgumentNotNull(id, "id");
object obj = this.index.Configuration.IndexFieldStorageValueFormatter.FormatValueForIndexStorage(id);
SolrQueryByField solrQueryByField = new SolrQueryByField("_group", obj.ToString());
SolrQueryByField solrQueryByField2 = new SolrQueryByField("_indexname", this.index.Name);
this.solr.Delete(solrQueryByField && solrQueryByField2);
this.CommitPolicyExecutor.IndexModified(this, id, IndexOperation.Delete);
}

Resources