web-dev-qa-db-ja.com

大きくなりすぎる可能性があるが古いデータが役に立たない文字列のリストを保存する方法

読み取り専用の外部サービスからの読み取りとして、特定の通知をユーザーに送信するアプリケーションを開発しています。ユーザーは通知を却下する可能性があり、それらは再び表示されるべきではありません。

時間の経過とともに変化する値に特に関心があるため、前回のクエリよりも新しいエントリのみをサーバーに要求することはできません。応募作品には少なくとも1週間ほどのチャンスを与える必要があります。そのため、サービスへのクエリは以前に取得されたデータを返す可能性があり、既に閉じられているデータをフィルター処理する必要があります。 SHAハッシュのように見える、受信したエントリのIDを確認することで、これを行うことができます。

これらのIDをid-> booleanペアとして、またはSQLiteデータベースにPreferencesに保存できますが、遅かれ早かれ制限に達する可能性があります。

また、古いエントリを実際に確認する必要はありません。たとえば、最新の100エントリにハードリミットを設定できますが、それで十分です。

制限を超えないようにするには、古いエントリを破棄する方法を教えてください。


編集:要求に応じて、役立つかもしれない問題に関する詳細情報:

  • 私のクエリは現在、「2週間よりも新しい場合、最新のものから最も古いものまで、最新の1000エントリ」という形式です。私のアプリケーションでは、1000は非常に高い数値であり、事実上無限です。 2週間は非常に長い時間間隔であり、その時間までに関連性が高くなる可能性は非常に低いため、ユーザーはその情報についてもう通知されたくないでしょう。

  • すべてのエントリには、「作成された」タイムスタンプがあります。また、それらには「更新された」タイムスタンプがあり、存在する場合は、アプリケーションの目的で「作成された」日付として扱う必要があります。ただし、この専門性を説明する回答は期待していません。

  • すべてのエントリには「重要度係数」があります。これは、追跡している値です。この係数が設定されたしきい値よりも高いエントリのみをユーザーに通知します。この値は時間の経過とともに変化するため、以前にフェッチして関連性がないことがわかったエントリを単に無視することはできません。この値の変更しないでください「更新された」フィールドに影響します。

  • ユーザーがエントリに関する通知を却下した場合、次にクエリが発生したときにその通知を除外する必要があります。 IDを比較するだけで十分です。

7
Pablo Almeida

ただのアイデアで、多分私は問題のいくつかのパラメーターを誤解しました。とにかく、私はソリューションを提供し、機能的なものに向けた取り組みを開始します。

取得時:

  • 読み取り専用データベースから、どちらか最後のクエリよりも新しいエントリor 1-2週間より新しいエントリのみを取得します
  • sQLiteデータベースに保存したIDとそれらのIDを比較して、すでに閉じられているエントリをフィルターで除外します

さらに、SQLiteデータベースのスペースが不足することを恐れている場合、またはとにかく古い却下された通知を忘れたい場合:

  • 毎週1回、SQLiteデータベースのどのエントリが2週間より古いかを確認し(読み取り専用データベースでクロスチェックを実行するか、SQLiteデータベースに開始日を保存するだけ)、それらを削除します
3
blue

セット理論の 補数演算 を使用。また、最近の通知が100に制限されていると想定しています。

Set<Notification> updateNotifications(Set<Notification> persisted, Set<Notification> recent) {
    Set<Notification> newNotifications = complement(recent, persisted);
    save(newNotifications);
    persisted = persisted.addAll(newNotifications);

    if (persisted.size() <= 100) {
        return persisted;
    }

    Set<Notification> obsoleteNotifications = complement(persisted, recent);
    delete(obsoleteNotifications);
    persisted = persisted.removeAll(obsoleteNotifications);

    return persisted;
}

class Notification {
    /* Fields provided by the service */
    boolean dismissed;
}

NotificationクラスはおそらくJSONから逆シリアル化され、dismissedはデフォルトでfalseに設定されています。各サービスのフェッチ後にupdateNotificationsを呼び出して、新しい通知を保存し、古い通知を削除します。新しい通知のみが保存されるため、以前に永続化された通知の却下されたフラグは保持されます。


タイムスタンプを使用すると、complementおよびdeleteをより効率的に実装できます。

1
user2418306

結果セットのすべてのフィールドをカバーするプロパティと、デフォルト値がfalseの追加の「Dismissed」プロパティを使用して、通知クラスまたは構造体を記述します。

アプリケーションの起動時に、格納されているソート済みの通知オブジェクトのリストを読み取ります(最初は空の場合があります)。タイムスタンプでソートする必要があります。あなたの限界にそれをトリミングします。その後定期的に

  • クエリを実行します。
  • それぞれについて、結果セットのレコードをループします。

    • 同じIDのオブジェクトを検索します。
    • dismissedプロパティがtrueの場合、続行/次へ。それ以外の場合は、レコードの通知オブジェクトを作成し、ソートされたリストに追加します。
  • コレクション内のまだ閉じられていないオブジェクトをユーザーに提示します。ユーザーにオブジェクトの読み取りと破棄を許可します。彼がそれを却下する場合、Dismissedプロパティをtrueに設定し、通知をビューから削除します。

アプリケーションの終了時に、通知コレクションを永続化します。

通知ビューが開いていてポーラーが作動している場合、通知コレクションが更新された後、ラウンドをスキップするか、ビューを更新する必要があります。

1
Martin Maat

あなたが言ったことと私の理解に従って、

  1. サーバーから結果をフェッチします。
  2. エントリが存在する場合はレコードを更新し、それ以外の場合は挿入します。
  3. 記録の有効期限を設定します(作成または更新された日付に2週間を追加します。どちらか大きい方/要件に応じて)。
  4. 期限切れのエントリを削除します。

また、ユーザーがエントリの通知を却下したときに、レコードにフラグを設定できます。

1