diff --git a/AUTHORS.md b/AUTHORS.md
index 7ac9408e14..4e305b9edf 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -175,6 +175,7 @@
 * [markusj](mailto:markusj@users.noreply.github.com)
 * [mnassabain](mailto:34754819+mnassabain@users.noreply.github.com)
 * [mormegil](mailto:mormegil@centrum.cz)
+* [nextcloud486153](mailto:78801830+nextcloud486153@users.noreply.github.com)
 * [nexus-uw](mailto:you@example.com)
 * [repat](mailto:repat@repat.de)
 * [ritchiewilson](mailto:rawilson52@gmail.com)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8428e94156..890b503597 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@ The format is mostly based on [Keep a Changelog](https://keepachangelog.com/en/1
 # Unreleased
 ## [18.x.x]
 ### Changed
+- Split user data out of feed fields for de-duplication
 
 ### Fixed
 
diff --git a/lib/Db/FeedMapperV2.php b/lib/Db/FeedMapperV2.php
index bab170f792..688e99f143 100644
--- a/lib/Db/FeedMapperV2.php
+++ b/lib/Db/FeedMapperV2.php
@@ -29,6 +29,7 @@
 class FeedMapperV2 extends NewsMapperV2
 {
     const TABLE_NAME = 'news_feeds';
+    const USER_TABLE_NAME = 'news_user_feeds';
 
     /**
      * FeedMapper constructor.
@@ -38,7 +39,7 @@ class FeedMapperV2 extends NewsMapperV2
      */
     public function __construct(IDBConnection $db, Time $time)
     {
-        parent::__construct($db, $time, Feed::class);
+        parent::__construct($db, $time, Feed::class, self::USER_TABLE_NAME);
     }
 
     /**
@@ -53,7 +54,7 @@ public function findAllFromUser(string $userId, array $params = []): array
     {
         $builder = $this->db->getQueryBuilder();
         $builder->select('feeds.*', $builder->func()->count('items.id', 'unreadCount'))
-            ->from(static::TABLE_NAME, 'feeds')
+            ->from(static::USER_TABLE_NAME, 'feeds')
             ->leftJoin(
                 'feeds',
                 ItemMapperV2::TABLE_NAME,
@@ -84,7 +85,7 @@ public function findFromUser(string $userId, int $id): Entity
     {
         $builder = $this->db->getQueryBuilder();
         $builder->select('*')
-            ->from(static::TABLE_NAME)
+            ->from(static::USER_TABLE_NAME)
             ->where('user_id = :user_id')
             ->andWhere('id = :id')
             ->setParameter('user_id', $userId)
@@ -102,7 +103,7 @@ public function findAll(): array
     {
         $builder = $this->db->getQueryBuilder();
         $builder->select('*')
-            ->from(static::TABLE_NAME)
+            ->from(static::USER_TABLE_NAME)
             ->where('deleted_at = 0');
 
         return $this->findEntities($builder);
@@ -123,7 +124,8 @@ public function findByURL(string $userId, string $url): Entity
     {
         $builder = $this->db->getQueryBuilder();
         $builder->select('*')
-            ->from(static::TABLE_NAME)
+            ->from(static::TABLE_NAME, 'feeds')
+            ->innerJoin('feeds', self::USER_TABLE_NAME, 'users', 'feeds.id = users.feed_id')
             ->where('user_id = :user_id')
             ->andWhere('url = :url')
             ->setParameter('user_id', $userId)
@@ -143,7 +145,7 @@ public function findAllFromFolder(?int $id): array
     {
         $builder = $this->db->getQueryBuilder();
         $builder->select('*')
-            ->from(static::TABLE_NAME);
+            ->from(static::USER_TABLE_NAME);
 
         if (is_null($id)) {
             $builder->where('folder_id IS NULL');
@@ -168,8 +170,8 @@ public function read(string $userId, int $id, ?int $maxItemID = null): int
     {
         $idBuilder = $this->db->getQueryBuilder();
         $idBuilder->select('items.id')
-            ->from(ItemMapperV2::TABLE_NAME, 'items')
-            ->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
+            ->from(ItemMapperV2::USER_TABLE_NAME, 'items')
+            ->innerJoin('items', FeedMapperV2::USER_TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
             ->andWhere('feeds.user_id = :userId')
             ->andWhere('feeds.id = :feedId')
             ->setParameter('userId', $userId)
@@ -188,7 +190,7 @@ function ($value): int {
         );
 
         $builder = $this->db->getQueryBuilder();
-        $builder->update(ItemMapperV2::TABLE_NAME)
+        $builder->update(ItemMapperV2::USER_TABLE_NAME)
             ->set('unread', $builder->createParameter('unread'))
             ->andWhere('id IN (:idList)')
             ->andWhere('unread != :unread')
diff --git a/lib/Db/FolderMapperV2.php b/lib/Db/FolderMapperV2.php
index ea2edee91d..0c30ed7eab 100644
--- a/lib/Db/FolderMapperV2.php
+++ b/lib/Db/FolderMapperV2.php
@@ -112,8 +112,8 @@ public function read(string $userId, int $id, ?int $maxItemId = null): int
     {
         $idBuilder = $this->db->getQueryBuilder();
         $idBuilder->select('items.id')
-                  ->from(ItemMapperV2::TABLE_NAME, 'items')
-                  ->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
+                  ->from(ItemMapperV2::USER_TABLE_NAME, 'items')
+                  ->innerJoin('items', FeedMapperV2::USER_TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
                   ->andWhere('feeds.user_id = :userId')
                   ->andWhere('feeds.folder_id = :folderId')
                   ->setParameter('userId', $userId)
@@ -129,7 +129,7 @@ public function read(string $userId, int $id, ?int $maxItemId = null): int
         }, $this->db->executeQuery($idBuilder->getSQL(), $idBuilder->getParameters())->fetchAll());
 
         $builder = $this->db->getQueryBuilder();
-        $builder->update(ItemMapperV2::TABLE_NAME)
+        $builder->update(ItemMapperV2::USER_TABLE_NAME)
             ->set('unread', $builder->createParameter('unread'))
             ->andWhere('id IN (:idList)')
             ->andWhere('unread != :unread')
diff --git a/lib/Db/ItemMapperV2.php b/lib/Db/ItemMapperV2.php
index 8a92354d80..08894a1faa 100644
--- a/lib/Db/ItemMapperV2.php
+++ b/lib/Db/ItemMapperV2.php
@@ -31,6 +31,7 @@
 class ItemMapperV2 extends NewsMapperV2
 {
     const TABLE_NAME = 'news_items';
+    const USER_TABLE_NAME = 'news_user_items';
 
     /**
      * ItemMapper constructor.
@@ -40,7 +41,7 @@ class ItemMapperV2 extends NewsMapperV2
      */
     public function __construct(IDBConnection $db, Time $time)
     {
-        parent::__construct($db, $time, Item::class);
+        parent::__construct($db, $time, Item::class, self::USER_TABLE_NAME);
     }
 
     /**
@@ -56,9 +57,8 @@ public function findAllFromUser(string $userId, array $params = []): array
         $builder = $this->db->getQueryBuilder();
         $builder->select('items.*')
                 ->from($this->tableName, 'items')
-                ->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
-                ->where('feeds.user_id = :user_id')
-                ->andWhere('feeds.deleted_at = 0')
+                ->innerJoin('items', self::USER_TABLE_NAME, 'users', 'items.id = users.item_id')
+                ->where('users.user_id = :user_id')
                 ->setParameter('user_id', $userId, IQueryBuilder::PARAM_STR);
 
         foreach ($params as $key => $value) {
@@ -92,10 +92,9 @@ public function findFromUser(string $userId, int $id): Entity
         $builder = $this->db->getQueryBuilder();
         $builder->select('items.*')
             ->from($this->tableName, 'items')
-            ->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
-            ->where('feeds.user_id = :user_id')
+            ->innerJoin('items', self::USER_TABLE_NAME, 'users', 'items.id = users.item_id')
+            ->where('users.user_id = :user_id')
             ->andWhere('items.id = :item_id')
-            ->andWhere('feeds.deleted_at = 0')
             ->setParameter('user_id', $userId, IQueryBuilder::PARAM_STR)
             ->setParameter('item_id', $id, IQueryBuilder::PARAM_INT);
 
@@ -444,9 +443,10 @@ public function findAllFeed(
     ): array {
         $builder = $this->db->getQueryBuilder();
 
-        $builder->select('items.*')
+        $builder->select('items.*', 'users.unread', 'users.starred', 'users.shared_by')
             ->from($this->tableName, 'items')
             ->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
+            ->innerJoin('items', self::USER_TABLE_NAME, 'users', 'items.id = users.item_id')
             ->andWhere('feeds.deleted_at = 0')
             ->andWhere('feeds.user_id = :userId')
             ->andWhere('items.feed_id = :feedId')
@@ -501,9 +501,10 @@ public function findAllFolder(
             $folderWhere = $builder->expr()->eq('feeds.folder_id', new Literal($folderId), IQueryBuilder::PARAM_INT);
         }
 
-        $builder->select('items.*')
+        $builder->select('items.*', 'users.unread', 'users.starred', 'users.shared_by')
             ->from($this->tableName, 'items')
             ->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
+            ->innerJoin('items', self::USER_TABLE_NAME, 'users', 'items.id = users.item_id')
             ->andWhere('feeds.user_id = :userId')
             ->andWhere('feeds.deleted_at = 0')
             ->andWhere($folderWhere)
@@ -550,11 +551,10 @@ public function findAllItems(
     ): array {
         $builder = $this->db->getQueryBuilder();
 
-        $builder->select('items.*')
+        $builder->select('items.*', 'users.unread', 'users.starred', 'users.shared_by')
             ->from($this->tableName, 'items')
-            ->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
-            ->andWhere('feeds.user_id = :userId')
-            ->andWhere('feeds.deleted_at = 0')
+            ->innerJoin('items', self::USER_TABLE_NAME, 'users', 'items.id = users.item_id')
+            ->andWhere('users.user_id = :userId')
             ->setParameter('userId', $userId)
             ->addOrderBy('items.id', ($oldestFirst ? 'ASC' : 'DESC'));
 
diff --git a/lib/Db/NewsMapperV2.php b/lib/Db/NewsMapperV2.php
index b33266f8b5..9500fec998 100644
--- a/lib/Db/NewsMapperV2.php
+++ b/lib/Db/NewsMapperV2.php
@@ -56,9 +56,10 @@ abstract class NewsMapperV2 extends QBMapper
     public function __construct(
         IDBConnection $db,
         Time $time,
-        string $entity
+        string $entity,
+        ?string $table = null
     ) {
-        parent::__construct($db, static::TABLE_NAME, $entity);
+        parent::__construct($db, $table ?? static::TABLE_NAME, $entity);
         $this->time = $time;
     }
 
diff --git a/lib/Migration/Version160100Date20210821130702.php b/lib/Migration/Version160100Date20210821130702.php
new file mode 100644
index 0000000000..6ed600672e
--- /dev/null
+++ b/lib/Migration/Version160100Date20210821130702.php
@@ -0,0 +1,141 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OCA\News\Migration;
+
+use Closure;
+use OCP\DB\ISchemaWrapper;
+use OCP\IDBConnection;
+use OCP\Migration\IOutput;
+use OCP\Migration\SimpleMigrationStep;
+
+/**
+ * Auto-generated migration step: Please modify to your needs!
+ */
+class Version160100Date20210821130702 extends SimpleMigrationStep {
+
+    /**
+     * @var IDBConnection
+     */
+    protected $connection;
+
+    public function __construct(IDBConnection $connection)
+    {
+        $this->connection = $connection;
+    }
+
+    /**
+     * @param IOutput $output
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
+     * @param array $options
+     */
+    public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
+    }
+
+    /**
+     * @param IOutput $output
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
+     * @param array $options
+     * @return null|ISchemaWrapper
+     */
+    public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
+        /** @var ISchemaWrapper $schema */
+        $schema = $schemaClosure();
+
+        if (!$schema->hasTable('news_user_items')) {
+            $table = $schema->createTable('news_user_items');
+            $table->addColumn('item_id', 'bigint', [
+                'notnull' => true,
+                'length' => 8,
+                'unsigned' => true,
+            ]);
+            $table->addColumn('user_id', 'string', [
+                'notnull' => true,
+                'length' => 64,
+            ]);
+            $table->addColumn('unread', 'boolean', [
+                'notnull' => true,
+                'default' => false,
+            ]);
+            $table->addColumn('starred', 'boolean', [
+                'notnull' => true,
+                'default' => false,
+            ]);
+            $table->addColumn('last_modified', 'bigint', [
+                'notnull' => false,
+                'length' => 8,
+                'default' => 0,
+                'unsigned' => true,
+            ]);
+            $table->addColumn('shared_by', 'string', [
+                'notnull' => false,
+                'length' => 64
+            ]);
+            $table->setPrimaryKey(['item_id', 'user_id']);
+        }
+
+        if (!$schema->hasTable('news_user_feeds')) {
+            $table = $schema->createTable('news_user_feeds');
+            $table->addColumn('feed_id', 'bigint', [
+                'notnull' => true,
+                'length' => 8,
+                'unsigned' => true,
+            ]);
+            $table->addColumn('user_id', 'string', [
+                'notnull' => true,
+                'length' => 64,
+            ]);
+            $table->addColumn('folder_id', 'bigint', [
+                'notnull' => false,
+                'length' => 8,
+            ]);
+            $table->addColumn('deleted_at', 'bigint', [
+                'notnull' => false,
+                'length' => 8,
+                'default' => 0,
+                'unsigned' => true,
+            ]);
+            $table->addColumn('added', 'bigint', [
+                'notnull' => false,
+                'length' => 8,
+                'default' => 0,
+                'unsigned' => true,
+            ]);
+            $table->addColumn('title', 'text', [
+                'notnull' => true,
+            ]);
+            $table->addColumn('last_modified', 'bigint', [
+                'notnull' => false,
+                'length' => 8,
+                'default' => 0,
+                'unsigned' => true,
+            ]);
+            $table->setPrimaryKey(['feed_id', 'user_id']);
+        }
+
+        return $schema;
+    }
+
+    /**
+     * @param IOutput $output
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
+     * @param array $options
+     */
+    public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
+        $qb = $this->connection->getQueryBuilder();
+        $user_item_table = $qb->getTableName('news_user_items');
+        $user_feed_table = $qb->getTableName('news_user_feeds');
+        $item_table = $qb->getTableName('news_items');
+        $feed_table = $qb->getTableName('news_feeds');
+
+        $items_query = "REPLACE INTO $user_item_table SELECT id AS 'item_id', ? AS 'user_id',`unread`,`starred`,`last_modified`,`shared_by` FROM $item_table where feed_id = ?;";
+
+        $feeds = $this->connection->executeQuery("SELECT `id`,`user_id` FROM $feed_table;")->fetchAll();
+        foreach ($feeds as $feed) {
+            $this->connection->executeUpdate($items_query, [$feed['user_id'], $feed['id']]);
+        }
+
+        $this->connection->executeUpdate("REPLACE INTO $user_feed_table SELECT id AS 'feed_id',user_id,folder_id,deleted_at,added,title,last_modified FROM $feed_table;");
+    }
+}
diff --git a/tests/Unit/Db/ItemMapperPaginatedTest.php b/tests/Unit/Db/ItemMapperPaginatedTest.php
index 9d44e0756e..f25f19b306 100644
--- a/tests/Unit/Db/ItemMapperPaginatedTest.php
+++ b/tests/Unit/Db/ItemMapperPaginatedTest.php
@@ -64,15 +64,13 @@ public function testFindAllItemsInvalid()
 
         $this->builder->expects($this->exactly(1))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(['items', 'news_user_items', 'users', 'items.id = users.item_id'])
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(3))
+        $this->builder->expects($this->exactly(2))
             ->method('andWhere')
             ->withConsecutive(
-                ['feeds.user_id = :userId'],
-                ['feeds.deleted_at = 0']
-            )
+                ['users.user_id = :userId'])
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(2))
@@ -129,14 +127,13 @@ public function testFindAllItemsFullInverted()
 
         $this->builder->expects($this->exactly(1))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(['items', 'news_user_items', 'users', 'items.id = users.item_id'])
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(3))
+        $this->builder->expects($this->exactly(2))
             ->method('andWhere')
             ->withConsecutive(
-                ['feeds.user_id = :userId'],
-                ['feeds.deleted_at = 0'],
+                ['users.user_id = :userId'],
                 ['items.id > :offset']
             )
             ->will($this->returnSelf());
@@ -196,14 +193,13 @@ public function testFindAllItemsUnread()
 
         $this->builder->expects($this->exactly(1))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(['items', 'news_user_items', 'users', 'items.id = users.item_id'])
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(4))
+        $this->builder->expects($this->exactly(3))
             ->method('andWhere')
             ->withConsecutive(
-                ['feeds.user_id = :userId'],
-                ['feeds.deleted_at = 0'],
+                ['users.user_id = :userId'],
                 ['items.id < :offset'],
                 ['items.unread = :unread']
             )
@@ -267,14 +263,13 @@ public function testFindAllItemsUnreadNoLimit()
 
         $this->builder->expects($this->exactly(1))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(['items', 'news_user_items', 'users', 'items.id = users.item_id'])
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(4))
+        $this->builder->expects($this->exactly(3))
             ->method('andWhere')
             ->withConsecutive(
-                ['feeds.user_id = :userId'],
-                ['feeds.deleted_at = 0'],
+                ['users.user_id = :userId'],
                 ['items.id < :offset'],
                 ['items.unread = :unread']
             )
@@ -336,14 +331,13 @@ public function testFindAllItemsStarred()
 
         $this->builder->expects($this->exactly(1))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(['items', 'news_user_items', 'users', 'items.id = users.item_id'])
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(4))
+        $this->builder->expects($this->exactly(3))
             ->method('andWhere')
             ->withConsecutive(
-                ['feeds.user_id = :userId'],
-                ['feeds.deleted_at = 0'],
+                ['users.user_id = :userId'],
                 ['items.id < :offset'],
                 ['items.starred = :starred']
             )
@@ -411,14 +405,13 @@ public function testFindAllItemsStarredSearch()
 
         $this->builder->expects($this->exactly(1))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(['items', 'news_user_items', 'users', 'items.id = users.item_id'])
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(6))
+        $this->builder->expects($this->exactly(5))
             ->method('andWhere')
             ->withConsecutive(
-                ['feeds.user_id = :userId'],
-                ['feeds.deleted_at = 0'],
+                ['users.user_id = :userId'],
                 ['items.id < :offset'],
                 ['items.search_index LIKE :term0'],
                 ['items.search_index LIKE :term1'],
@@ -490,9 +483,12 @@ public function testFindAllFeed()
             ->with('news_items', 'items')
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(1))
+        $this->builder->expects($this->exactly(2))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(
+                ['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'],
+                ['items', 'news_user_items', 'users', 'items.id = users.item_id']
+            )
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(4))
@@ -563,9 +559,12 @@ public function testFindAllFeedNoLimit()
             ->with('news_items', 'items')
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(1))
+        $this->builder->expects($this->exactly(2))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(
+                ['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'],
+                ['items', 'news_user_items', 'users', 'items.id = users.item_id']
+            )
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(4))
@@ -634,9 +633,12 @@ public function testFindAllFeedInverted()
             ->with('news_items', 'items')
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(1))
+        $this->builder->expects($this->exactly(2))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(
+                ['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'],
+                ['items', 'news_user_items', 'users', 'items.id = users.item_id']
+            )
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(4))
@@ -705,9 +707,12 @@ public function testFindAllFeedHideRead()
             ->with('news_items', 'items')
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(1))
+        $this->builder->expects($this->exactly(2))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(
+                ['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'],
+                ['items', 'news_user_items', 'users', 'items.id = users.item_id']
+            )
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(5))
@@ -782,9 +787,12 @@ public function testFindAllFeedSearch()
             ->with('news_items', 'items')
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(1))
+        $this->builder->expects($this->exactly(2))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(
+                ['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'],
+                ['items', 'news_user_items', 'users', 'items.id = users.item_id']
+            )
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(6))
@@ -875,9 +883,12 @@ public function testFindAllFolderIdNull()
             ->with('news_items', 'items')
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(1))
+        $this->builder->expects($this->exactly(2))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(
+                ['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'],
+                ['items', 'news_user_items', 'users', 'items.id = users.item_id']
+            )
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(4))
@@ -960,9 +971,12 @@ public function testFindAllFolderIdNullNoLimit()
             ->with('news_items', 'items')
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(1))
+        $this->builder->expects($this->exactly(2))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(
+                ['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'],
+                ['items', 'news_user_items', 'users', 'items.id = users.item_id']
+            )
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(4))
@@ -1043,9 +1057,12 @@ public function testFindAllFolderHideRead()
             ->with('news_items', 'items')
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(1))
+        $this->builder->expects($this->exactly(2))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(
+                ['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'],
+                ['items', 'news_user_items', 'users', 'items.id = users.item_id']
+            )
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(5))
@@ -1129,9 +1146,12 @@ public function testFindAllFolderHideReadInvertOrder()
             ->with('news_items', 'items')
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(1))
+        $this->builder->expects($this->exactly(2))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(
+                ['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'],
+                ['items', 'news_user_items', 'users', 'items.id = users.item_id']
+            )
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(5))
@@ -1218,9 +1238,12 @@ public function testFindAllFolderSearchId()
             ->with('news_items', 'items')
             ->will($this->returnSelf());
 
-        $this->builder->expects($this->exactly(1))
+        $this->builder->expects($this->exactly(2))
             ->method('innerJoin')
-            ->withConsecutive(['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'])
+            ->withConsecutive(
+                ['items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id'],
+                ['items', 'news_user_items', 'users', 'items.id = users.item_id']
+            )
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(6))
diff --git a/tests/Unit/Db/ItemMapperTest.php b/tests/Unit/Db/ItemMapperTest.php
index 7fc45018e2..5a9241a5eb 100644
--- a/tests/Unit/Db/ItemMapperTest.php
+++ b/tests/Unit/Db/ItemMapperTest.php
@@ -88,17 +88,15 @@ public function testFindAllFromUser()
 
         $this->builder->expects($this->once())
             ->method('innerJoin')
-            ->with('items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id')
+            ->withConsecutive(
+                ['items', 'news_user_items', 'users', 'items.id = users.item_id'],
+                ['a', 'a', 'a', 'a']
+            )
             ->will($this->returnSelf());
 
         $this->builder->expects($this->once())
             ->method('where')
-            ->with('feeds.user_id = :user_id')
-            ->will($this->returnSelf());
-
-        $this->builder->expects($this->once())
-            ->method('andWhere')
-            ->with('feeds.deleted_at = 0')
+            ->with('users.user_id = :user_id')
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(1))
@@ -149,17 +147,12 @@ public function testFindAllFromUserWithParams()
 
         $this->builder->expects($this->once())
             ->method('innerJoin')
-            ->with('items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id')
+            ->with('items', 'news_user_items', 'users', 'items.id = users.item_id')
             ->will($this->returnSelf());
 
         $this->builder->expects($this->once())
             ->method('where')
-            ->with('feeds.user_id = :user_id')
-            ->will($this->returnSelf());
-
-        $this->builder->expects($this->exactly(2))
-            ->method('andWhere')
-            ->withConsecutive(['feeds.deleted_at = 0'], ['key = :val'])
+            ->with('users.user_id = :user_id')
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(1))
@@ -291,17 +284,17 @@ public function testFindFromUser()
 
         $this->builder->expects($this->once())
             ->method('innerJoin')
-            ->with('items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id')
+            ->with('items', 'news_user_items', 'users', 'items.id = users.item_id')
             ->will($this->returnSelf());
 
         $this->builder->expects($this->once())
             ->method('where')
-            ->with('feeds.user_id = :user_id')
+            ->with('users.user_id = :user_id')
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(2))
             ->method('andWhere')
-            ->withConsecutive(['items.id = :item_id'], ['feeds.deleted_at = 0'])
+            ->withConsecutive(['items.id = :item_id'], ['users.deleted_at = 0'])
             ->will($this->returnSelf());
 
         $this->builder->expects($this->exactly(2))