我正在尝试测试Firebase,以允许用户使用push
发表评论。我想用以下内容显示我检索的数据;
fbl.child('sell').limit(20).on("value", function(fbdata) {
// handle data display here
}
问题是数据按最旧到最新的顺序返回 - 我希望它按相反的顺序排列。 Firebase可以这样做吗?
答案 0 :(得分:42)
自撰写此答案以来,Firebase添加了一项功能,允许任何子项或按值排序。因此,现在有四种订购数据的方式:按键,按值,按优先级或按任何指定子项的值。请参阅此blog post that introduces the new ordering capabilities。
但基本方法仍然相同:
1。添加具有反转时间戳的子属性,然后对其进行排序。
2。按升序读取子项,然后在客户端上反转它们。
Firebase支持以两种方式检索集合的子节点:
你现在得到的是名字,这恰好是按时间顺序排列的。这并非巧合btw:当你将一个项目push
加入一个集合时,会生成这个名称以确保以这种方式订购这些孩子。引用Firebase documentation for push
:
push()生成的唯一名称以客户端生成的时间戳为前缀,以便按时间顺序对结果列表进行排序。
Firebase guide on ordered data就此主题发表了这样的话:
如何订购数据
默认情况下,Firebase节点上的子项按名称按字典顺序排序。使用
push()
可以生成按时间顺序自然排序的子名称,但许多应用程序需要以其他方式对其数据进行排序。 Firebase允许开发人员通过为每个项目指定自定义优先级来指定列表中项目的顺序。
获取所需行为的最简单方法是在添加项目时指定始终递减的优先级:
var ref = new Firebase('https://your.firebaseio.com/sell');
var item = ref.push();
item.setWithPriority(yourObject, 0 - Date.now());
您还必须以不同方式检索孩子:
fbl.child('sell').startAt().limit(20).on('child_added', function(fbdata) {
console.log(fbdata.exportVal());
})
在我的测试中使用on('child_added'
确保添加的最后几个子项以反向时间顺序返回。另一方面,使用on('value'
按照名称的顺序返回它们。
请务必阅读section "Reading ordered data",其中说明child_*
事件用于检索(订购)儿童的用法。
用于演示此内容的文件夹:http://jsbin.com/nonawe/3/watch?js,console
答案 1 :(得分:11)
从firebase 2.0.x开始,您可以使用limitLast()
来实现:
fbl.child('sell').orderByValue().limitLast(20).on("value", function(fbdataSnapshot) {
// fbdataSnapshot is returned in the ascending order
// you will still need to order these 20 items in
// in a descending order
}
答案 2 :(得分:7)
为了增加弗兰克的答案,通过简单地使用{{1},即使您还没有使用优先顺序来排序,也可以获取最新的记录。喜欢这个 demo :
endAt().limit(x)
请注意,这甚至可能达到一千条记录(假设有效载荷很小),效果非常好。对于更强大的用法,弗兰克的答案是权威的,更具可扩展性。
通过监控var fb = new Firebase(URL);
// listen for all changes and update
fb.endAt().limit(100).on('value', update);
// print the output of our array
function update(snap) {
var list = [];
snap.forEach(function(ss) {
var data = ss.val();
data['.priority'] = ss.getPriority();
data['.name'] = ss.name();
list.unshift(data);
});
// print/process the results...
}
/ child_added
/ child_removed
事件代替child_moved
,可以优化此暴力以处理更大的数据或更多记录,并使用debounce批量应用DOM更新,而不是单独应用。
自然,无论采用什么方法,DOM更新都是一个臭味,一旦你进入数百个元素,所以去抖方法(或React.js解决方案,本质上是一个超级的去抖)是一个很好的工具
答案 3 :(得分:4)
实际上没有办法,但似乎我们有了这个
的recyclerview query=mCommentsReference.orderByChild("date_added");
query.keepSynced(true);
// Initialize Views
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
mManager = new LinearLayoutManager(getContext());
// mManager.setReverseLayout(false);
mManager.setReverseLayout(true);
mManager.setStackFromEnd(true);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(mManager);
答案 4 :(得分:3)
我有一个日期变量(长)并希望将最新项目保留在列表顶部。所以我做的是:
答案 5 :(得分:3)
您正在搜索limitTolast(Int x)。这将为您提供最后一个" x"数据库的更高元素(它们按升序排列)但它们是" x"更高要素
如果你进入你的数据库{10,300,150,240,2,24,220}
这种方法:
myFirebaseRef.orderByChild("highScore").limitToLast(4)
会回复你:{150,220,240,300}
答案 6 :(得分:3)
在Android中,有一种方法可以通过适配器实际反转对象的Arraylist中的数据。在我的情况下,我无法使用LayoutManager以降序反转结果,因为我使用水平Recyclerview来显示数据。将以下参数设置为recyclerview会搞砸我的UI体验:
llManager.setReverseLayout(true);
llManager.setStackFromEnd(true);
我发现这个唯一的工作方式是通过RecyclerView适配器的BindViewHolder方法:
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
final SuperPost superPost = superList.get(getItemCount() - position - 1);
}
希望这个答案能够帮助所有在Firebase中遇到此问题的开发人员。
答案 7 :(得分:2)
我使用ReactFire轻松进行Firebase集成。
基本上,它可以帮助我将数据存储到组件状态,如Dim lRow As Long
With Sheets("11937")
lRow = .Range("B" & .Rows.Count).End(xlUp).Row
.Range("A2:AL" & lRow).Copy Destination:=Sheets("STS").Range("C2")
End With
。然后,我必须使用的是array
函数(read more)
以下是我如何做到这一点:
reverse()
答案 8 :(得分:2)
Firebase:如何以相反的顺序显示项目的主题,每个请求都有一个限制,以及“加载更多”按钮的指示符。
FBRef.child( “childName”) .limitToLast(loadMoreLimit)//例如loadMoreLimit = 10
这将获得最后10个项目。获取列表中最后一条记录的id并为负载保存更多功能。接下来,将对象集合转换为数组并执行list.reverse()。
LOAD MORE功能:下一个调用将执行两项操作,它将根据第一个请求中的引用ID获取下一个列表项序列,并在需要显示“加载更多”时为您提供指示“按钮。
this.FBRef .child( “childName”) .endAt(null,lastThreadId)//从上一步中获取此信息 .limitToLast(loadMoreLimit + 2)
您需要删除此对象集合的第一个和最后一个项目。第一项是获取此列表的参考。最后一项是显示更多按钮的指示器。
我有一堆其他逻辑可以保持一切清洁。您只需要为加载更多功能添加此代码。
list = snapObjectAsArray; // The list is an array from snapObject
lastItemId = key; // get the first key of the list
if (list.length < loadMoreLimit+1) {
lastItemId = false;
}
if (list.length > loadMoreLimit+1) {
list.pop();
}
if (list.length > loadMoreLimit) {
list.shift();
}
// Return the list.reverse() and lastItemId
// If lastItemId is an ID, it will be used for the next reference and a flag to show the "load more" button.
}
答案 9 :(得分:1)
有一种更好的方法。您应该按负服务器时间戳排序。如何获得负面服务器时间戳甚至离线?有一个隐藏的领域有帮助。文档中的相关摘录:
var offsetRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/.info/serverTimeOffset");
offsetRef.on("value", function(snap) {
var offset = snap.val();
var estimatedServerTimeMs = new Date().getTime() + offset;
});
答案 10 :(得分:1)
要添加DaveVávra的答案,我使用负时间戳作为我的sort_key
,如此
<强>设置强>
const timestamp = new Date().getTime();
const data = {
name: 'John Doe',
city: 'New York',
sort_key: timestamp * -1 // Gets the negative value of the timestamp
}
<强>获取强>
const ref = firebase.database().ref('business-images').child(id);
const query = ref.orderByChild('sort_key');
return $firebaseArray(query); // AngularFire function
这将从最新到最旧获取所有对象。您还可以$indexOn
sortKey
使其运行得更快
答案 11 :(得分:1)
我也遇到了这个问题,我找到了一个非常简单的解决方案,该解决方案无论如何都不需要处理数据。如果要将结果保存到DOM,请使用某种列表。您可以使用flexbox并设置一个类来反转其容器中的元素。
.reverse {
display: flex;
flex-direction: column-reverse;
}
答案 12 :(得分:0)
我是通过前置完成的。
query.orderByChild('sell').limitToLast(4).on("value", function(snapshot){
snapshot.forEach(function (childSnapshot) {
// PREPEND
});
});
答案 13 :(得分:0)
有人指出有两种方法可以做到这一点:
我发现这样做的最简单方法是使用选项1,但通过LinkedList
。我只是将每个对象附加到堆栈的前面。它足够灵活,仍允许列表在ListView
或RecyclerView
中使用。这种方式即使它们按最新到最新的顺序排列,您仍然可以查看或检索最新到最旧的。
答案 14 :(得分:0)
您可以添加名为orderColumn的列,以节省时间
Long refrenceTime = "large future time";
Long currentTime = "currentTime";
Long order = refrenceTime - currentTime;
现在在名为orderColumn的列中保存Long order并在检索数据时保存 如orderBy(orderColumn),你将得到你需要的东西。
答案 15 :(得分:0)
只需在数组上使用reverse()
,假设您将值存储到数组items[]
然后执行this.items.reverse()
ref.subscribe(snapshots => {
this.loading.dismiss();
this.items = [];
snapshots.forEach(snapshot => {
this.items.push(snapshot);
});
**this.items.reverse();**
},
答案 16 :(得分:0)
myarray.reverse();或this.myitems = items.map(item => item).reverse();
答案 17 :(得分:0)
对我来说,Measure1 = [i for i in df.columns if i.startswith('Measrue1')]
Measure2 = [i for i in df.columns if i.startswith('Measrue2')]
final = []
for i in Measure1:
for j in Measure2:
if(i.split('_')[1]==j.split('_')[1]):
final.append((i,j))
rows = len(final)
values = ','.join([f"'{i.split('_')[1]}',{i},{j}" for i,j in final])
有效。我还发现df.select('cust',expr(f'''stack({rows},{values})''').alias('Month','Measure1','Measure2')).show()
+----+------+--------+--------+
|cust| Month|Measure1|Measure2|
+----+------+--------+--------+
| 1|month1| 10| 10|
| 1|month2| 20| 20|
| 1|month3| 30| 30|
| 1|month4| 40| 40|
| 1|month5| 50| 50|
| 2|month1| 10| 10|
| 2|month2| 20| 20|
| 2|month3| 30| 30|
| 2|month4| 40| 40|
| 2|month5| 50| 50|
+----+------+--------+--------+
不是函数:)
limitToLast
以上是对我有用的。