【问题标题】:Firebase use endAt if timestamp field如果时间戳字段,Firebase 使用 endAt
【发布时间】:2018-11-29 16:05:26
【问题描述】:

我有这个字段的记录:

age: 25
timestamp: 1484089199472

此记录插入者:

@Exclude
public Map<String, Object> toMap() {
    HashMap<String, Object> result = new HashMap<>();

    result.put("age", age);
    result.put("timestamp", ServerValue.TIMESTAMP);
    return result;
}

如果我使用endAt(24,"age") 比它的工作好,该项目是不可见的。

但如果我想在时间戳中使用 endAt,它就不起作用。例如: endAt(100000,"timestamp") 并且该行保持可见。 为什么?

这是检查类型?

如何过滤?

我不知道! :( 我希望有一个人可以帮助我! 谢谢!

编辑:

查询获取实际日期行

 @Override
    public Query getQuery(final DatabaseReference databaseReference) {
        Date endTime = new Date();
        endTime.setHours(23);
        endTime.setMinutes(59);
        endTime.setSeconds(59);

        return databaseReference
                .child("toplist")
                .endAt(endTime.getTime(),"timestamp")
                .orderByChild("point")
                .limitToFirst(50);

    }

数据

@IgnoreExtraProperties
public class Rank{

    public int number;
    public String username;
    public int point;


    // [START post_to_map]
    @Exclude
    public Map<String, Object> toMap() {
        HashMap<String, Object> result = new HashMap<>();
        result.put("number", number);
        result.put("username", username);
        result.put("point", point);
        result.put("timestamp", ServerValue.TIMESTAMP);
        return result;
    }

}

添加新的随机项目

private void writeNewRandomTopListItem() {
        Random rnd = new Random();
        Rank item = new Rank();
        item.username = "Test " + rnd.nextInt(20000);
        item.point = rnd.nextInt(2000000);

        mDatabase.child("toplist").push().setValue(item.toMap());
    }

适配器

Query postsQuery = getQuery(mDatabase);
        mAdapter = new FirebaseRecyclerAdapter<Rank, PostViewHolder>(Rank.class, R.layout.item_post, PostViewHolder.class, postsQuery) {
            @Override
            protected void populateViewHolder(final PostViewHolder viewHolder, final Rank model, final int position) {

                viewHolder.bindToPost(model,position);
            }
        };
        mRecycler.setAdapter(mAdapter);

...

 toplist
   -Ka8m3hN-vRjPZhKH3Rt
     number: 0
     point:  1269424
     timestamp: 148407253222471
     username:  "Test 19727"
   -Ka8m3hWRIQKL7faNqUS
     number:  0
     point:  1398061
     timestamp:  1484075322472
     username: "Test 17679"

【问题讨论】:

  • 您能否提供更高级别的数据库数据以及有关您正在调用的确切查询的更多代码?如果你愿意,我很确定我能帮助你。
  • 感谢您的帮助。我编辑了我的帖子。

标签: android firebase firebase-realtime-database


【解决方案1】:

您应该首先按timestamp 子节点对节点进行排序,然后在客户端按points 对收到的项目进行排序。这被描述为here

我建议你改用这个查询:

@Override
public Query getQuery(final DatabaseReference databaseReference) {
    Date endTime = new Date();
    endTime.setHours(23);
    endTime.setMinutes(59);
    endTime.setSeconds(59);

    return databaseReference.child("toplist").orderByChild("timestamp")
            .endAt(endTime.getTime()).limitToFirst(50);
}

通过这种方式,您告诉 Firebase 按其子节点之一对您的节点进行排序,在本例中为 timestamp。希望这会有所帮助。

接下来,您需要在客户端对数据进行排序。这样的一个问题是,来自 firebase 的实时更改不会在 RecyclerView 中重新排序您的项目。

我再次建议阅读this 的答案。

【讨论】:

  • endAt 现在运行良好。但我得到了第二个 orderByChild 的错误
  • java.lang.IllegalArgumentException: 你不能合并多个 orderBy 调用!
  • 是的,你是对的,忘记了。我将编辑我的答案。
【解决方案2】:

经过几天的实验,我解决了这个问题。

重点是,

我惊讶地发现即使查询也可以按深度嵌套排序 孩子,但它只适用于孩子 ONE 更高级别!

在这种情况下,我尝试先向下一层节点,并在其上查询特定时间段,它可以工作。

这是我在 Firebase 实时数据库上的数据树:

为了读取存储在 Firebase 中的 POJO 模型,我设置了一个辅助类来为我服务。 所以我运行FirebaseDatabaseHelper.getInstance().readCatalogFromDatabase(Card.class, listener, start, end); 同时用最新的数据库更新我的用户界面。

关于我的 FirebaseDatabaseHelper,有两种相关方法可以很好地帮助我读取数据库 reference() 上的模型,它指的是包含许多模型的父节点,例如“/Card/user_id”节点,其中包含一堆子节点,表示卡片详细信息在 /Card/user_id/card_id”。

/**
 * attaches listener to obtain values at child locations of "catalog/" storing lots of models in JSON tree
 * reads values created in a specific period and ordered by date
 *
 * catalog: "Card" for card
 *          "Comment" for comment
 *
 * It's surprised to found out even query can be ordered by deep nested children, but children ONE more level down only
 * Being such circumstance, go for node one more level down first and do query for a specific period on it
 */
public void readCatalogFromDatabase(final Class<?> clazz, final OnReadDatabaseChildEventListener child_listener, final long start, final long end) {
    //Logger.d(">>> end at date before:" + (end/(1*24*60*60*1000) - start/(1*24*60*60*1000)));
    Logger.d(">>> start:" + start + ", end:" + end);
    DatabaseReference referenceCatalog;
    OnReadDatabaseValueEventListener ids_listener;
    String catalog;
    if (clazz.getName().equals(Card.class.getName())) {
        ids_listener = new OnReadDatabaseValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                List<String> ids = new LinkedList<>();
                Logger.d("... user count:" + dataSnapshot.getChildrenCount());
                /**
                 * $ROOT/catalog/user_id/CardId/CardId
                 * $ROOT/catalog/user_id/CardId/ProfilePhoto
                 * $ROOT/catalog/user_id/CardId/ProfileTitle
                 * $ROOT/catalog/user_id/CardId/ProfileName
                 * $ROOT/catalog/user_id/CardId/ProfileID
                 * $ROOT/catalog/user_id/CardId/ArticleTitle
                 * $ROOT/catalog/user_id/CardId/ArticleContent
                 * $ROOT/catalog/user_id/CardId/ArticleCount
                 * $ROOT/catalog/user_id/CardId/ArticlePhoto
                 * $ROOT/catalog/user_id/CardId/ArticlePhotoFileName
                 * $ROOT/catalog/user_id/CardId/Distance
                 * $ROOT/catalog/user_id/CardId/Date
                 *      ^[key]  :[value]                -> initial
                 *              ^[key]  :[value]        -> 1th for-loop
                 */
                for (DataSnapshot snapShotOfUserId : dataSnapshot.getChildren()) {
                    Logger.d("... user(" + snapShotOfUserId.getKey() + ") post count:" + snapShotOfUserId.getChildrenCount());
                    ids.add(snapShotOfUserId.getKey());
                }
                for (String id : ids) readListFromDatabase(clazz, id, child_listener, start, end);
                FirebaseDatabaseHelper.getInstance().detachValueEventListener(this);
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                child_listener.onCancelled(databaseError);
                FirebaseDatabaseHelper.getInstance().detachValueEventListener(this);
            }
        };
        catalog = Card.class.getSimpleName();
        referenceCatalog = getDatabaseChild(catalog, null, null);
        referenceCatalog.orderByKey().limitToLast(COUNT_ON_PAGE).addListenerForSingleValueEvent(ids_listener);
        mValueEventListeners.put(ids_listener, referenceCatalog);
    } else if (clazz.getName().equals(Comment.class.getName())) {
        ids_listener = new OnReadDatabaseValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                List<String> ids = new LinkedList<>();
                Logger.d("... card count:" + dataSnapshot.getChildrenCount());
                /**
                 * $ROOT/catalog/card_id/CommentId/CardId
                 * $ROOT/catalog/card_id/CommentId/CommentId
                 * $ROOT/catalog/card_id/CommentId/ProfilePhoto
                 * $ROOT/catalog/card_id/CommentId/ProfileName
                 * $ROOT/catalog/card_id/CommentId/ProfileID
                 * $ROOT/catalog/card_id/CommentId/Comment
                 * $ROOT/catalog/card_id/CommentId/Distance
                 * $ROOT/catalog/card_id/CommentId/Date
                 *      ^[key]  :[value]                    -> initial
                 *              ^[key]  :[value]            -> 1th for-loop
                 */
                for (DataSnapshot snapShotOfCardId : dataSnapshot.getChildren()) {
                    Logger.d("... card(" + snapShotOfCardId.getKey() + ") comment count:" + snapShotOfCardId.getChildrenCount());
                    ids.add(snapShotOfCardId.getKey());
                }
                for (String id : ids) readListFromDatabase(clazz, id, child_listener, start, end);
                FirebaseDatabaseHelper.getInstance().detachValueEventListener(this);
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                child_listener.onCancelled(databaseError);
                FirebaseDatabaseHelper.getInstance().detachValueEventListener(this);
            }
        };
        catalog = Comment.class.getSimpleName();
        referenceCatalog = getDatabaseChild(catalog, null, null);
        referenceCatalog.orderByKey().limitToLast(COUNT_ON_PAGE).addListenerForSingleValueEvent(ids_listener);
        mValueEventListeners.put(ids_listener, referenceCatalog);
    }

然后去,

 /**
 * attaches listener to obtain values at child locations of "catalog/id/" storing list of models in JSON tree
 * reads values created in a specific period and ordered by date
 *
 * id: user id for card
 *     card id for comment
 *
 * query can be ordered by deep nested ONE more level down children
 */
public void readListFromDatabase(Class<?> clazz, String id, OnReadDatabaseChildEventListener listener, long start, long end) {
    //Logger.d(">>> end at date before:" + (end/(1*24*60*60*1000) - start/(1*24*60*60*1000)));
    Logger.d(">>> start:" + start + ", end:" + end + ", id:" + id);
    DatabaseReference referenceCatalog;
    Query query;
    String catalog;
    if (clazz.getName().equals(Card.class.getName())) {
        catalog = Card.class.getSimpleName();
        referenceCatalog = getDatabaseChild(catalog, id, null);
        query = referenceCatalog.orderByChild("Date").startAt(start).endAt(end).limitToLast(COUNT_ON_PAGE);
        query.addChildEventListener(listener);
        mChildEventListeners.put(listener, referenceCatalog);
    } else if (clazz.getName().equals(Comment.class.getName())) {
        catalog = Comment.class.getSimpleName();
        referenceCatalog = getDatabaseChild(catalog, id, null);
        query = referenceCatalog.orderByChild("Date").startAt(start).endAt(end).limitToLast(COUNT_ON_PAGE);
        query.addChildEventListener(listener);
        mChildEventListeners.put(listener, referenceCatalog);
    }
}

关于数据库参考,

/**
 * gets a database reference to location headed with "/catalog/", "/id/" and "/key/" as prefixes(to a child location in JSON tree)
 *
 * id: user id for card
 *     card id for comment
 * key:
 *     card id for card
 *     comment id for comment
 */
private DatabaseReference getDatabaseChild(String catalog, String id, String key) {
    Logger.d(">>>");
    DatabaseReference reference;
    if (catalog == null) {
        if (id == null) {
            if (key == null) {
                Logger.d("... catalog:" + catalog + ", id:" + id + ", key:" + key);
                reference = FirebaseDatabase.getInstance().getReference();
            } else {
                Logger.d("... catalog:" + catalog + ", id:" + id + ", key:" + key);
                reference = FirebaseDatabase.getInstance().getReference(key);
            }
        } else {
            if (key == null) {
                Logger.d("... catalog:" + catalog + ", id:" + id + ", key:" + key);
                reference = FirebaseDatabase.getInstance().getReference(id);
            } else {
                Logger.d("... catalog:" + catalog + ", id:" + id + ", key:" + key);
                reference = FirebaseDatabase.getInstance().getReference(id + "/" + key);
            }
        }
    } else {
        if (id == null) {
            if (key == null) {
                Logger.d("... catalog:" + catalog + ", id:" + id + ", key:" + key);
                reference = FirebaseDatabase.getInstance().getReference(catalog);
            } else {
                Logger.d("... catalog:" + catalog + ", id:" + id + ", key:" + key);
                reference = FirebaseDatabase.getInstance().getReference(catalog + "/" + key);
            }
        } else {
            if (key == null) {
                Logger.d("... catalog:" + catalog + ", id:" + id + ", key:" + key);
                reference = FirebaseDatabase.getInstance().getReference(catalog + "/" + id);
            } else {
                Logger.d("... catalog:" + catalog + ", id:" + id + ", key:" + key);
                reference = FirebaseDatabase.getInstance().getReference(catalog + "/" + id + "/" + key);
            }
        }
    }
    return reference;
}

这就是我在特定时期去查询的方式。

此外,我发现了一些关于人们应该打电话的答案 addChildEventListener() 关注orderByChild();然而,之后 运行实验,我说,

Query query;
query = referenceCatalog.orderByChild("Date").startAt(start).endAt(end).limitToLast(COUNT_ON_PAGE);
query.addChildEventListener(listener);

referenceCatalog.orderByChild("Date").startAt(start).endAt(end).limitToLast(COUNT_ON_PAGE).addChildEventListener(listener);

它们是一样的。

我认为他们的区别在于人们使用匿名 Java 编程的方式 上课与否。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-17
    • 2021-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-26
    • 2017-03-05
    相关资源
    最近更新 更多