I am currently making an app using Firebase.
It is one of those bulletin boards that can be seen anywhere on the web.
But there was one problem.
This is a matter of date sorting.
I want to look at the recent date first, but I always see only the data I created first.
postRef.orderByChild('createData').startAt(reverseDate).limitToFirst(1).on('child_added',(data)=>{
console.log(data.val().name + data.val().createData);
})
result - >hello1496941142093
My firebase tree
My code is the same as above.
How can I check my recent posts first?
How Do I order reverse of firebase database?
The Firebase Database will always return results in ascending order. There is no way to reverse them.
There are two common workaround for this:
Let the database do the filtering, but then reverse the results client-side.
Add an inverted value to the database, and use that for querying.
These options have been covered quite a few times before. So instead of repeating, I'll give a list of previous answers:
Display posts in descending posted order
Sort firebase data in descending order using negative timestamp
firebase sort reverse order
Is it possible to reverse a Firebase list?
many more from this list: https://www.google.com/search?q=site:stackoverflow.com+firebase+reverse%20sort%20javascript
You can simply make a function to reverse the object and then traversing it.
function reverseObject(object) {
var newObject = {};
var keys = [];
for (var key in object) {
keys.push(key);
}
for (var i = keys.length - 1; i >= 0; i--) {
var value = object[keys[i]];
newObject[keys[i]]= value;
}
return newObject;
}
This is how I solved it:
First I made a query in my service where I filter by date in milliseconds:
getImages (): Observable<Image[]> {
this.imageCollection = this.asf.collection<Image>('/images', ref => ref.orderBy('time').startAt(1528445969388).endAt(9999999999999));
this.images = this.imageCollection.snapshotChanges().pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data() as Image;
const id = a.payload.doc.id;
return { id, ...data };
}))
);
return this.images;
}
Then to get the newest date first I added this to my component where I call the method from my service:
let date = new Date;
let time = 9999999999999 - date.getTime();
console.log(time);
I pass the time let as the date. Since a newer date will be a bigger number to deduct from the 9999999999999, the newest date will turn up first in my query inside my service.
Hope this solved it for you
If you want to display it in the front end, I suggest that after you retrieve the data, use the reverse() function of JavaScript.
Example:
let result = postRef
.orderByChild("createData")
.startAt(reverseDate)
.limitToFirst(1)
.on("child_added", data => {
console.log(data.val().name + data.val().createData);
});
result.reverse();
Ive ended changing how I create my list on the frontend part.
was
posts.add(post);
changed to
posts.insert(0, post);
You could use a method where you save the same or alternate child with a negative value and then parse it.
postRef.orderByChild('createData').orderByChild('createData').on('child_added',(data)=>{
console.log(data.val().name + data.val().createData);})
Far more easier is just use Swift's reversed():
https://developer.apple.com/documentation/swift/array/1690025-reversed
https://developer.apple.com/documentation/swift/reversedcollection
let decodedIds = try DTDecoder().decode([String].self, from: value)
// we reverse it, because we want most recent orders at the top
let reversedDecodedIds = decodedIds.reversed().map {$0}
orderBy("timestamp", "desc")
I think you can give a second argument name "desc".
It worked for me
Related
I have an array of available users that can be invited and also another array with all joined users to the particular chat. I need to check which of the available users have joined the chat and should be listed elsewhere.
Finally, I want to get an array with only the available users who have not joined the chat.
let availablеUsers = [{id:1,name:'Dani'}, {id:2,name:'Ani'}, {id:3,name:'Marta'}]
let allUsers = [{id:2,name:'Ani'},{id:10,name:'John'}, {id:3,name:'Marta'}]
The first thing I try to do is find those who are already participating in the chat:
let joinedUsers = availablеUsers.map((user) => {
return allUsers?.find((u) => u.id === user.id);
});
And i get this : [undefined, {… Аni}, {… Marta}]
Then I try to filter the array of available users so that I remove from it those that are in the newly created array and here's the problem I don't know how to do this :/
My idea is something like that:
availablеUsers = availablеUsers.filter((user) => {
//HERE I don't know what logic to write
return joinedUsers?.map((m) => m?.id !== user.id); // this doesn't work, just an example
});
My goal is to have only those users not contained in the other remain in the availableUsers array.
In the example I have given at the end in the array should remain only {id:1,name:'Dani'}
I welcome any suggestions. If it can do it with chaining, without the extra variable for joinedUsers it would be even better!
There's no need for joinedUsers. Just use find() or some() in the filter() callback, and invert the test.
availableUsers = availableUsers.filter(user => !allUsers.some(u => u.id == user.id))
if users are uniquely identified by id you can use just a filter with a Set of known users:
let availablеUsers = [{id:1,name:'Dani'}, {id:2,name:'Ani'}, {id:3,name:'Marta'}]
let allUsers = [{id:2,name:'Ani'},{id:10,name:'John'}, {id:3,name:'Marta'}]
let joinedUsers = availablеUsers.filter(
function ({id}) {
return this.has(id);
},
new Set(allUsers.map(({id}) => id))
);
Accordingly, you can use the same to update availablеUsers in one go:
availablеUsers = availablеUsers.filter(
function ({id}) {
return !this.has(id);
},
new Set(allUsers.map(({id}) => id))
);
it's not super clear why or when you need !== vs === but the concept is: use a set and use filter instead of map when you want to filter + a Set works harder while constructed but it's blazing fast while used via has()
This is my code for update many records with mongodb.
const nfts = await waxModel.find();
console.log(nfts.length) // -> 121
// Option 1: using map()
nfts.map(async nft => {
nft.trait_attribute = null;
await nft.save();
});
// Option 2: using loop
for (let i = 0; i < nfts.length; i++) {
nfts[i].trait_attribute = null;
await nfts[i].save();
}
This is my DB, no recored have trait_attribute: null:
This is the first result when I use map(), only have 2 records:
And this is the second result when I use for loop:
I don't know that is the problem. In my previous question: I know map methods don't handle the asynchronous function but it's still have full records not missing many updated records as now.
Thank for your attention.
It looks like your code doesn't handle race conditions well.
The first option saves every nft simultaneously whilst the second one saves them one at a time. A more readable way to do that would be using a for-of loop:
for (const nft of nfts) {
nft.trait_attribute = null;
await nft.save();
}
I have a json file with the following data which I would like to group by Year , Theme and then average values on each theme. Can someone help me with this? I have grouped by date and then theme but struggling after that.
[
{"Bid":"BidTest1","QNo":"1","Score":"0.7","Theme":"Social Value","QDate":"01/01/2021"},
{"Bid":"BidTest1","QNo":"2","Score":"0.5","Theme":"Tech Mgt","QDate":"01/01/2021"},
{"Bid":"BidTest1","QNo":"3","Score":"0.8","Theme":"Agile","QDate":"01/01/2021"},
{"Bid":"BidTest1","QNo":"4","Score":"0.7","Theme":"Social Value","QDate":"01/01/2021"},
{"Bid":"BidTest456","QNo":"1","Score":"0.5","Theme":"Tech Mgt","QDate":"03/04/2021"},
{"Bid":"BidTest456","QNo":"2","Score":"0.7","Theme":"Social Value","QDate":"03/04/2021"},
{"Bid":"BidTest456","QNo":"3","Score":"0.5","Theme":"Agile","QDate":"03/04/2021"},
{"Bid":"BidHO","QNo":"1","Score":"0.8","Theme":"Agile","QDate":"06/10/2021"},
{"Bid":"BidHO","QNo":"2","Score":"0.7","Theme":"Social Value","QDate":"06/10/2021"}
]
The code I have used for grouping it is
let result1 = dataQ1.reduce((state1, current1 ) => {
let {QDate, Theme} = current1;
let date = state1[QDate] || (state1[QDate] = {});
let themeArr = date[Theme] || (date[Theme] = []);
// let monthArr = yearObj[month] || (yearObj[month] = []);
themeArr.push(current1);
return state1;
}, {});
This gives me an object with objects containing arrays for each Theme. I need to create a chart grouped by Month, Theme and mark the respective average values per theme.Final Chart.Final Data Sample
Could someone please guide me on how to go about this ? Thanks
I would slightly change your reducing function to make it easier to compute averages:
let groupedDataQ1 = dataQ1.reduce((accumulator, item) => {
let {QDate, Theme} = item;
accumulator[Theme] = accumulator[Theme] || {};
// i'm assuming your dates are in dd/mm/yyyy format -> we extract mm/yyyy
let month = QDate.slice(-7);
(accumulator[Theme][month] = accumulator[Theme][month] || []).push(item);
return accumulator;
}, {});
Now you have as keys the Themes, and each Theme is an object that, for each month, has an array of corresponding values. So, if you want to compute the average Scores for Theme "Agile" in April 2021 you would simply do
let agile_april_data = groupedDataQ1['Agile']['04/2021'];
let agile_april_avg_score = agile_april_data.reduce((val, item) => val + parseFloat(item.Score),0) / agile_april_data.length
The reason why I decided to change the first term of the grouping function (you group first by date [leaving aside the fact that you keep the day in the key], and then by Theme, while I do the other way around) is because in the screenshot examples you provided, the Theme is the series over which the computations are performed - so, for each Theme, one line in the plot and one table in the tabular data. What happens if, for a month, you don't have any data for a specific Theme? You would need to perform a big amount of checks, while in this approach you only need to iterate over the object keys.
not able to check the unique values log showing all values getting
added to the array
.
var moveToReady = [];
var topLinesRecords = new GlideRecord('x_snc_ms_dynamics_d365_queue');
topLinesRecords.addEncodedQuery('root_element_sys_id=03133e1a1bfe6410f8ca0e16624bcba7');
topLinesRecords.orderByDesc('sys_created_on');
topLinesRecords.query();
while(topLinesRecords.next()){
gs.info(' first record : ' + topLinesRecords.number);
if(moveToReady.indexOf(topLinesRecords.getValue('object_sys_id')) == -1){
moveToReady.push(topLinesRecords.getValue('object_sys_id'));
}
gs.info('array. : ' + moveToReady);
updateRecordtoFail(topLinesRecords);
}
You can use the Set structure from ES6 to make your code faster and more readable:
// Create Set
this.items = new Set();
add(item) {
this.items.add(item);
// Set to array
console.log([...this.items]);
}
you may use array.includes
if (!moveToReady.includes(topLinesRecords.getValue('object_sys_id'))){
moveToReady.push(topLinesRecords.getValue('object_sys_id'));
}
So, some tips to get unique values on ServiceNow:
-GlideRecord has a "getUniqueValue" method
(URL: https://docs.servicenow.com/bundle/paris-platform-administration/page/administer/table-administration/concept/c_UniqueRecordIdentifier.html)
-You can search on your Script Includes a OOB method/function to get only unique values. Search for "utils". Every instance has this, maybe "ArrayUtils".
Hope this information helped!
I'm trying to add two related items to my Firebase database. I want to push one item, then get that item's newly created key and use it as the key for the second item in a different tree. I've tried querying the database to get the last key created and using it as the key for the second push, but it's still just generating a new key for it. Here's the code that I'm using:
save: function() {
if (this.$.document.isNew && (this.editableCard.title || this.editableCard.body)) {
return this.$.document.save(this.cardsPath).then(function() {
this.$.document.reset();
var sceneRef = firebase.database().ref().child(this.cardsPath);
var scene = sceneRef.orderByKey().limitToLast(1);
var sceneKey = scene.key;
this.$.document.save('/documents/', sceneKey);
}.bind(this));
}
return Promise.resolve();
}
(I'm using Polymer, and my starting point is the note-app demo for Polymerfire).
Any ideas on how I can retrieve the new key of the first push and use it for the second push? Thanks!
EDIT
I found the answer in Firebase's documentation for Reading and Writing to the database for Web. Link
push() returns a DatabaseReference immediately. You can ask that reference what its key is, using getKey(), then use that string to update another location in your database.
You can access the key property on the original database reference and use that as the key for the second one, like so:
let firstObjRef = firebase.database().ref('/first/path/).push(firstObj, (error) => {
videoObj["roomUploadedTo"] = this.roomName;
var updateObj = {};
updateObj[videoObjRef.key] = videoObj;
firebase.database().ref('/second/path/').update(updateObj).then( (e) => {
console.log('update went through. booyah! ' + e);
})