# Topic\_views vs Topic.views

**URL:** https://meta.discourse.org/t/topic-views-vs-topic-views/97175
**Category:** Development
**Created:** [September 14, 2018, 8:25am UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175 "2018-09-14T08:25:31Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [September 14, 2018, 8:25am UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/1 "2018-09-14T08:25:31Z")

</div>

When helping a client with a [data explorer](https://meta.discourse.org/t/32566?silent=true) query, they noticed a difference between the topic views returned by the query, and the number on the category topic list.

Where does the difference between

`SELECT COUNT(*) FROM topic_views WHERE topic_id = X`

and

`Topic.find(X).views`

come from?

---

<div class="post-metadata">

### Author: ![vinothkannans](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/vinothkannans/32/86465_2.png) [@vinothkannans](https://meta.discourse.org/u/vinothkannans)
#### Post date: [September 14, 2018, 10:47am UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/2 "2018-09-14T10:47:52Z")

</div>

> [@Topic view count is inaccurate in topic index](https://meta.discourse.org/t/topic-view-count-is-inaccurate-in-topic-index/56764/8):
>
> Note that topic view counts are reset once per 8 hours per IP (for anons). So if you had a lot of anon visitors coming from the same IP that won’t show up in view counts.

`Topic.views` is integer count which includes both user and anonymous traffic.

`SELECT COUNT(*) FROM topic_views WHERE topic_id = X` is used to track topic views by registered users. It will have below details.

> <https://github.com/discourse/discourse/blob/cb824a6b338b32216baef9021fe508a290e99bbe/app/models/topic_view_item.rb#L59-L62>

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [September 15, 2018, 9:56am UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/3 "2018-09-15T09:56:50Z")

</div>

> [@vinothkannans](#):
>
> used to track topic views by registered users

No, that is not entirely true. `topic_views` registers anonymous views as well, in those cases `user_id` is `null`.

So what’s I think that’s left is that `Topic.views` counts for anonymous users are counted once per `topic_view_duration_hours` (default: 8) hours per IP, and `topic_views` for anonymous users are counted [once per IP](https://meta.discourse.org/t/problematic-ip-address-fields/83785/30)?

---

<div class="post-metadata">

### Author: ![vinothkannans](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/vinothkannans/32/86465_2.png) [@vinothkannans](https://meta.discourse.org/u/vinothkannans)
#### Post date: [September 15, 2018, 10:02am UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/4 "2018-09-15T10:02:08Z")

</div>

Yes I can see now. As per the index `uniq_ip_or_user_id_topic_views` either user id or ip address is required.

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [September 15, 2018, 10:05am UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/5 "2018-09-15T10:05:05Z")

</div>

So what is the intended use of `topic_views` ?

For registering statistics about topic views it would make sense if it used the same rules as `Topic.views`.

For registering which user saw what topic it wouldn’t make sense to register IP addresses for anonymous visitors (which is a left over GDPR toxic item anyway)

EDIT: it seems like TopicViewItem is only being used for registering which user/IP saw what topic, and that is only used in TL3 requirement calculations. So that would mean that we could (optionally) get rid of registering IP addresses for anonymous visitors and be a bit more GDPR compliant? Or am I going too quickly now?

---

<div class="post-metadata">

### Author: ![vinothkannans](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/vinothkannans/32/86465_2.png) [@vinothkannans](https://meta.discourse.org/u/vinothkannans)
#### Post date: [September 15, 2018, 10:20am UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/6 "2018-09-15T10:20:14Z")

</div>

In a 20 users private community a topic can have 100 views count. Since new topic visits after `topic_view_duration_hours` are calculated as new view count. But `select count(*) from topic_views where topic_id = X` will never exceed the count 20. That’s why Topic.views count is different. This is applicable for open communities too.

> [@RGJ](#):
>
> which is a left over GDPR toxic item anyway

I’m not sure here. I will check it on Monday.

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [September 16, 2018, 11:32pm UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/7 "2018-09-16T23:32:25Z")

</div>

> [@RGJ](#):
>
> So what’s I think that’s left is that `Topic.views` counts for anonymous users are counted once per `topic_view_duration_hours` (default: 8) hours per IP, and `topic_views` for anonymous users are counted [once per IP](https://meta.discourse.org/t/problematic-ip-address-fields/83785/30)?

Sounds about right.

Long term I don’t even see much value in carrying topic views in the raw form in the topic\_views table for longer than a few months.

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [September 27, 2018, 9:22pm UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/8 "2018-09-27T21:22:39Z")

</div>

> [@vinothkannans](#):
>
> I’m not sure here. I will check it on Monday.

Did you check already?

---

<div class="post-metadata">

### Author: ![vinothkannans](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/vinothkannans/32/86465_2.png) [@vinothkannans](https://meta.discourse.org/u/vinothkannans)
#### Post date: [September 28, 2018, 8:55am UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/9 "2018-09-28T08:55:03Z")

</div>

> [@GDPR countdown and compliance](https://meta.discourse.org/t/gdpr-countdown-and-compliance/87190):
>
> As we’re quickly approaching May 25th, here’s my (perhaps naive) understanding of certain key Discourse GDPR issues: Right to Be Forgotten white_check_markIf the user requests, the admin can use the user info panel to delete all of a user’s posts. Note you may need to up the “delete user max post age” and “delete all posts max” settings but then it’s possible. Once there are no more posts you can then delete the user. Alternatively, a less disruptive solution is the “Anonymize User” button …

> [@Problematic IP address fields](https://meta.discourse.org/t/problematic-ip-address-fields/83785):
>
> Continuing the discussion from [Providing data for GDPR](https://meta.discourse.org/t/providing-data-for-gdpr/83595/17): I did a first pass over Discourse’s tables, and I found several places where IP addresses are being accidentally correlated with user IDs. This is toxic data generating liability for Discourse forums. List of problematic IP address fields: white_check_mark x incoming\_links: stores timestamped IP address correlated with user ID and an exact post ID, topic ID, and Referer: header Fixed Storage: PR#5826white_check_mark …

It’s already discussed in above topics.

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [September 28, 2018, 9:10am UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/10 "2018-09-28T09:10:47Z")

</div>

It’s discussed there, but there is no solution. IP addresses for anonymous visitors are still being stored.

> [@Problematic IP address fields](https://meta.discourse.org/t/problematic-ip-address-fields/83785/29):
>
> Although I do absolutely welcome these PR’s I do want to emphasize that storing the IP addresses of visitors without an account (for a longer time than needed for deduplication) is a much more problematic issue since those people cannot easily be asked to give their consent.

So I guess we’re back at my former statement:

> [@RGJ](#):
>
> For registering which user saw what topic it wouldn’t make sense to register IP addresses for anonymous visitors (which is a left over GDPR toxic item anyway)

---

<div class="post-metadata">

### Author: ![codinghorror](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/codinghorror/32/110067_2.png) [@codinghorror](https://meta.discourse.org/u/codinghorror)
#### Post date: [September 28, 2018, 9:12am UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/11 "2018-09-28T09:12:38Z")

</div>

I don’t think we have quite gotten around to it, but it is definitely on our list. If you would like it to be done faster, have you considered contributing a PR to get it done?

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [September 28, 2018, 10:24am UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/12 "2018-09-28T10:24:02Z")

</div>

> [@codinghorror](#):
>
> have you considered contributing a PR to get it done

Absolutely, but first I wanted to have some kind of confirmation that changing this would be actually welcome.

To sum it all up, I think we could get rid of the `ip_address` column in the `topic_views` table altogether, and stop creating entries for anonymous users, right?

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [September 28, 2018, 10:47am UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/13 "2018-09-28T10:47:31Z")

</div>

No we need to roll this up into a different table, I want to retain 1 day fidelity on page views

---

<div class="post-metadata">

### Author: ![izzy](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/izzy/32/156031_2.png) [@izzy](https://meta.discourse.org/u/izzy)
#### Post date: [December 12, 2018, 7:37pm UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/14 "2018-12-12T19:37:46Z")

</div>

I’m running into this too, but on a pretty hefty scale.

![image](https://global.discourse-cdn.com/meta/optimized/3X/c/5/c5f9a6cc760bad7c2872f4273e5e868e8f1a6191_2_690x78.png) The topic itself shows ![image](https://global.discourse-cdn.com/meta/original/3X/8/e/8ee51214f4e18a61a7967679b26b1666d84baa21.png).

Was it confirmed that

> [@RGJ](#):
>
> `topic_views` for anonymous users are counted [once per IP](https://meta.discourse.org/t/problematic-ip-address-fields/83785/30)?

The only reason it’s grinding my gears is that the `Topic.views` is static-- You can’t do an analysis of how many views there were on this day last year, because it doesn’t record each view-- just adds to the running count.

Is there some way using another table to get a full list of views on a per-record basis?

---

<div class="post-metadata">

### Author: ![Mittineague](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mittineague/32/114259_2.png) [@Mittineague](https://meta.discourse.org/u/Mittineague)
#### Post date: [December 12, 2018, 8:24pm UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/15 "2018-12-12T20:24:17Z")

</div>

When a member views a topic a row is INSERTed (or UPDATEd) into the topic\_user table  
[discourse/app/models/topic\_user.rb at main · discourse/discourse · GitHub](https://github.com/discourse/discourse/blob/master/app/models/topic_user.rb)

```plaintext
# user_id :integer not null
# topic_id :integer not null
# posted :boolean default(FALSE), not null
# last_read_post_number :integer
# highest_seen_post_number :integer
# last_visited_at :datetime
# first_visited_at :datetime
# notification_level :integer default(1), not null
# notifications_changed_at :datetime
# notifications_reason_id :integer
# total_msecs_viewed :integer default(0), not null
# cleared_pinned_at :datetime
# id :integer not null, primary key
# last_emailed_post_number :integer
# liked :boolean default(FALSE)
# bookmarked :boolean default(FALSE)

```

I have a feeling it would cause a resource hit and not be a good choice as a frequently run task, but you should be able to use a count of the datetimes to get something more granular than a running total.

---

<div class="post-metadata">

### Author: ![izzy](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/izzy/32/156031_2.png) [@izzy](https://meta.discourse.org/u/izzy)
#### Post date: [December 12, 2018, 9:53pm UTC](https://meta.discourse.org/t/topic-views-vs-topic-views/97175/16 "2018-12-12T21:53:45Z")

</div>

I’d think that using topic\_user would return the same count of views as the topic\_views table would (which has full records) since that’s the one that stores user data-- what I’m missing is the record-level data for anonymous viewers with the same IP, but honestly, just knowing what the discrepancy there was is pretty much good enough 🙂
