【问题标题】:Is there a way to conditional sort in two fields in Realm?有没有办法在 Realm 的两个字段中进行条件排序?
【发布时间】:2017-07-07 05:30:43
【问题描述】:

我有一个评级领域对象列表如下:

public class RatingRealmObject extends RealmObject {

    @SerializedName("average")
    private float average;
    @SerializedName("raters")
    private int raters;

    public float getAverage() {
        return average;
    }

    public void setAverage(float average) {
        this.average = average;
    }

    public int getRaters() {
        return raters;
    }

    public void setRaters(int raters) {
        this.raters = raters;
    }
}

我想按平均降序对 RealmResultList 进行排序,但评分者的数量应大于或等于 5。

例如如果我们有两个食谱 A 和 B。

  • A 的平均评分为 4,没有。的评分者为 8 并且,

  • B 的平均评分为 5,没有。评分者为 4

那么在排序之后,A 应该在列表中排在第一位。

任何帮助如何在领域查询中创建条件。

【问题讨论】:

  • 所以您仍然希望列表中所有评分者少于 5 人的评分,但它们应该位于底部(也已排序)?
  • @ChristianMelchior 是的。
  • @EpicPandaForce ,对我的问题没用。
  • @ChristianMelchior,我尝试在非托管领域对象中使用比较器进行排序,但 realm.copyFromRealm(recipeRealmResult) 冻结了我的 UI 线程。我有大约 30k 个对象。任何帮助将不胜感激。

标签: android realm realm-list


【解决方案1】:

一种可能的解决方案是将两个 RealmResult 连接在一起以获得您想要的排序,请参阅here


另一种解决方案是,如果您使用附加字段扩展架构

public class RatingRealmObject extends RealmObject {
    @Inedx
    private float average;

    private int raters;

    @Index
    private int hasOverFiveRaters; // 0 or 1 like a TINYINT in SQLite

    public float getAverage() {
        return average;
    }

    public void setAverage(float average) {
        this.average = average;
    }

    public int getRaters() {
        return raters;
    }

    public void setRaters(int raters) {
        this.raters = raters;
        this.hasOverFiveRaters = raters >= 5 ? 1 : 0;
    }
}

因为现在you can do

realm.where(RatingRealmObject.class)
     .findAllSortedAsync(
         new String[] {"hasOverFiveRaters", "average"}, 
         new Sort[] { Sort.DESCENDING, Sort.DESCENDING });

P.S.: realm.copyFromRealm() 从 Realm 复制每个元素(在您的情况下,在 UI 线程上),因此删除了惰性评估,除非您尝试这样做,否则通常不需要也不建议这样做创建一个分离的可修改对象或希望通过 GSON 发送 RealmObject。

【讨论】:

  • 在使用 GSON 库时如何调用 setter 方法?
  • 对于 API 响应和 Realm 模式,我总是有单独的对象;但除此之外,您可以使用 TypeAdapter 让 GSON 做任何您想做的事情
【解决方案2】:

您可以在您的RatingRealmObject 中定义一个weight 字段,并在您设置averageraters 时计算weight。然后解决方案将就像按weight 排序一样简单。

一些例子:

public class RatingRealmObject extends RealmObject {
    private float average;
    private int raters;
    @Index
    private float weight;

    private void computeWeight() {
        // This is for showing the idea, you need to change how to calculate the weight depends on your requirement.
        weight = raters / 5 + average;
    }

    public float getAverage() {
        return average;
    }

    public void setAverage(float average) {
        this.average = average;
        computeWeight();
    }

    public int getRaters() {
        return raters;
    }

    public void setRaters(int raters) {
        this.raters = raters;
        computeWeight();
    }
}

那么你可以只使用realm.where(RatingRealmObject.class).findAllSortedAsync("weight");

【讨论】:

    【解决方案3】:

    @EpicPandaForce 和 @beeender 谢谢你们,你们帮我解决了这个问题。
    由于我正在使用 GSON 库进行反序列化,因此按照 GSON 指南,setter 方法不会调用。所以 Rating 对象中的额外字段计算对我不起作用。

    我已经通过@EpicPandaForce 提供的第一个解决方案解决了我的问题。

    List<RecipeRealmObject> ratingMoreThan5List = recipeRealmResult.where().greaterThanOrEqualTo("rating.raters", 5).findAllSorted("rating.average", Sort.DESCENDING);
                        List<RecipeRealmObject> ratingLessThan5List = recipeRealmResult.where().lessThan("rating.raters", 5).findAllSorted("rating.average", Sort.DESCENDING);
                        List<RecipeRealmObject> ratingNullList = recipeRealmResult.where().isNull("rating").findAll();
    
                        List<RecipeRealmObject> recipeList = new ArrayList<>();
                        recipeList.addAll(ratingMoreThan5List);
                        recipeList.addAll(ratingLessThan5List);
                        recipeList.addAll(ratingNullList);
                        onCompleteListener.onSearchComplete(recipeList);
    

    【讨论】:

    • setter method does not call. So additional field computation in Rating object didn't work for me. 这就是为什么我总是建议 RealmObject 和 API 响应使用单独的对象;否则 registerTypeAdapter 也可以工作
    猜你喜欢
    • 2019-06-27
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多