Repository: fossasia/open-event-server

Issue:
My Sessions: Server is returning duplicated data
**Describe the bug**
My Session is showing session's multiple times 


**Expected behaviour**
Server should return session only once

**Screenshots**
[![multiple session](http://img.youtube.com/vi/EMXLyCehYCM/0.jpg)](http://www.youtube.com/watch?v=EMXLyCehYCM "multiple session")

Responses for Reference :
https://github.com/fossasia/open-event-frontend/pull/3811#issuecomment-575883439
https://github.com/fossasia/open-event-frontend/pull/3811#issuecomment-575882180


Discussion:
cc: @iamareebjamal @mrsaicharan1 
@kushthedude - Are you working on this?
You may proceed!

On Wed, 22 Jan, 2020, 19:11 Suneet Srivastava, <notifications@github.com>
wrote:

> @kushthedude <https://github.com/kushthedude> - Are you working on this?
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/fossasia/open-event-server/issues/6763?email_source=notifications&email_token=AKQMTLX7DZC4FHRQL4RFWC3Q7BEI5A5CNFSM4KKD36S2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJTSXXY#issuecomment-577186783>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AKQMTLVXYZRIPAWPUFCHFXDQ7BEI5ANCNFSM4KKD36SQ>
> .
>

@kushthedude @iamareebjamal - Is their a specific case for sessions to return duplicated data.?

For me, I have a user with two sessions which have been submitted but not accepted. But the api returns correct data.

`http://127.0.0.1:5000/v1/users/2/sessions?sort=starts-at`

Response:
```
{
    "data": [
        {
            "type": "session",
            "attributes": {
                "is-mail-sent": false,
                "ends-at": null,
                "subtitle": "Helloe",
                "comments": "Hi I am admin ediiting it now",
                "complex-field-values": null,
                "language": "Hindi",
                "level": "Hard",
                "deleted-at": null,
                "audio-url": null,
                "is-locked": false,
                "last-modified-at": "2020-01-20T13:59:18.881961+00:00",
                "average-rating": null,
                "short-abstract": "Suneet Srivastava EevtnyayaSuneet Srivastava EevtnyayaSuneet Srivastava Eevtnyaya",
                "starts-at": null,
                "title": "Suneet Srivastava Eventyay2",
                "state": "pending",
                "signup-url": null,
                "long-abstract": "Suneet Srivastava EevtnyayaSuneet Srivastava EevtnyayaSuneet Srivastava EevtnyayaSuneet Srivastava Eevtnyaya",
                "submitted-at": "2019-12-29T19:24:13.010000+00:00",
                "slides-url": null,
                "video-url": null,
                "created-at": "2019-12-29T19:24:13.068583+00:00"
            },
            "relationships": {
                "microlocation": {
                    "links": {
                        "self": "/v1/sessions/2/relationships/microlocation",
                        "related": "/v1/sessions/2/microlocation"
                    }
                },
                "track": {
                    "links": {
                        "self": "/v1/sessions/2/relationships/track",
                        "related": "/v1/sessions/2/track"
                    }
                },
                "feedbacks": {
                    "links": {
                        "self": "/v1/sessions/2/relationships/feedbacks",
                        "related": "/v1/sessions/2/feedbacks"
                    }
                },
                "speakers": {
                    "links": {
                        "self": "/v1/sessions/2/relationships/speakers",
                        "related": "/v1/sessions/2/speakers"
                    }
                },
                "session-type": {
                    "links": {
                        "self": "/v1/sessions/2/relationships/session-type",
                        "related": "/v1/sessions/2/session-type"
                    }
                },
                "creator": {
                    "links": {
                        "self": "/v1/sessions/2/relationships/creator",
                        "related": "/v1/sessions/2/creator"
                    }
                },
                "event": {
                    "links": {
                        "self": "/v1/sessions/2/relationships/event",
                        "related": "/v1/sessions/2/event"
                    }
                }
            },
            "id": "2",
            "links": {
                "self": "/v1/sessions/2"
            }
        },
        {
            "type": "session",
            "attributes": {
                "is-mail-sent": false,
                "ends-at": null,
                "subtitle": null,
                "comments": "Synet123123677",
                "complex-field-values": null,
                "language": null,
                "level": null,
                "deleted-at": null,
                "audio-url": null,
                "is-locked": false,
                "last-modified-at": "2020-01-20T17:19:01.228848+00:00",
                "average-rating": null,
                "short-abstract": "Suneet Sassas",
                "starts-at": null,
                "title": "Suneet Srivastava",
                "state": "pending",
                "signup-url": null,
                "long-abstract": null,
                "submitted-at": "2019-12-28T13:09:16.567000+00:00",
                "slides-url": null,
                "video-url": null,
                "created-at": "2019-12-28T13:09:16.653535+00:00"
            },
            "relationships": {
                "microlocation": {
                    "links": {
                        "self": "/v1/sessions/1/relationships/microlocation",
                        "related": "/v1/sessions/1/microlocation"
                    }
                },
                "track": {
                    "links": {
                        "self": "/v1/sessions/1/relationships/track",
                        "related": "/v1/sessions/1/track"
                    }
                },
                "feedbacks": {
                    "links": {
                        "self": "/v1/sessions/1/relationships/feedbacks",
                        "related": "/v1/sessions/1/feedbacks"
                    }
                },
                "speakers": {
                    "links": {
                        "self": "/v1/sessions/1/relationships/speakers",
                        "related": "/v1/sessions/1/speakers"
                    }
                },
                "session-type": {
                    "links": {
                        "self": "/v1/sessions/1/relationships/session-type",
                        "related": "/v1/sessions/1/session-type"
                    }
                },
                "creator": {
                    "links": {
                        "self": "/v1/sessions/1/relationships/creator",
                        "related": "/v1/sessions/1/creator"
                    }
                },
                "event": {
                    "links": {
                        "self": "/v1/sessions/1/relationships/event",
                        "related": "/v1/sessions/1/event"
                    }
                }
            },
            "id": "1",
            "links": {
                "self": "/v1/sessions/1"
            }
        }
    ],
    "links": {
        "self": "/v1/users/2/sessions?sort=starts-at"
    },
    "meta": {
        "count": 4
    },
    "jsonapi": {
        "version": "1.0"
    }
}
```
http://127.0.0.1:5000/v1/users/2/sessions?page%5Bsize%5D=10&page%5Bnumber%5D=1&include=event&sort=starts-at

By removing the filter also works fine for me.


I have given the API Link above it is returning same sessions for page 2
and 3. Same is the case on local

On Sun, 26 Jan, 2020, 20:51 Suneet Srivastava, <notifications@github.com>
wrote:

>
> http://127.0.0.1:5000/v1/users/2/sessions?page%5Bsize%5D=10&page%5Bnumber%5D=1&include=event&sort=starts-at
>
> By removing the filter also works fine for me.
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/fossasia/open-event-server/issues/6763?email_source=notifications&email_token=AKQMTLXLUUFIU6ETPZZSWVLQ7WTAVA5CNFSM4KKD36S2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJ5WK3Y#issuecomment-578512239>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AKQMTLQXEQ2SIFPWZB2FKJTQ7WTAVANCNFSM4KKD36SQ>
> .
>

@codedsun Because there are not even enough items to do pagination, so obviously it'll return correct data
Ok will check it out.

On Sun, Jan 26, 2020, 9:06 PM Areeb Jamal <notifications@github.com> wrote:

> @codedsun <https://github.com/codedsun> Because there are not even enough
> items to do pagination, so obviously it'll return correct data
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/fossasia/open-event-server/issues/6763?email_source=notifications&email_token=AEYZISA355KZMY43FCQI2KDQ7WUW3A5CNFSM4KKD36S2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJ5WUXA#issuecomment-578513500>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AEYZISG23CQGRBC4AIOPBOLQ7WUW3ANCNFSM4KKD36SQ>
> .
>

Since the merged PR has been reverted. Reopening this issue, also please check https://github.com/fossasia/open-event-server/issues/6794 for reason why the PR was reverted .
I'll take a look at this.
@mrsaicharan1 #6794 was actual solution but it doesn't work with sort parameter, so that needs to be fixed
@iamareebjamal - If we change the queery to 
`                query_.distinct(Session.id, Session.starts_at).join(User)` it will work.

the error occurs because the Order by runs on different field and distinct runs on another one
Great, send a PR so we can revert it when `?order_by=ends_at` crashes. That is not the solution
@iamareebjamal - Nopes this isn't the right solution. I am looking for more
Paste the SQL query generated in the statement with and without distinct

Resolving patch:
diff --git a/app/api/sessions.py b/app/api/sessions.py
--- a/app/api/sessions.py
+++ b/app/api/sessions.py
@@ -1,5 +1,7 @@
+from flask import request
 from flask_jwt_extended import current_user
 from flask_rest_jsonapi import ResourceDetail, ResourceList, ResourceRelationship
+from flask_rest_jsonapi.querystring import QueryStringManager as QSManager
 
 from app.api.bootstrap import api
 from app.api.events import Event
@@ -95,6 +97,28 @@ def after_create_object(self, session, data, view_kwargs):
     }
 
 
+def get_distinct_sort_fields(schema, model, sort=True):
+    """Due to the poor code of flask-rest-jsonapi, distinct query needed
+       in sessions API to remove duplicate sessions can't be sorted on
+       returning subquery, thus we need to add all sort fields in distinct
+       group and repeat it in sort group as well"""
+    fields = []
+    qs = QSManager(request.args, schema)
+    for sort_opt in qs.sorting:
+        field = sort_opt['field']
+        if not hasattr(model, field):
+            continue
+        field = getattr(model, field)
+        if sort:
+            field = getattr(field, sort_opt['order'])()
+        fields.append(field)
+    field = Session.id
+    if sort:
+        field = field.desc()
+    fields.append(field)
+    return fields
+
+
 class SessionList(ResourceList):
     """
     List Sessions
@@ -131,6 +155,8 @@ def query(self, view_kwargs):
                         or Session.speakers.any(Speaker.user_id == user.id)
                     )
                 )
+                .distinct(*get_distinct_sort_fields(SessionSchema, Session, sort=False))
+                .order_by(*get_distinct_sort_fields(SessionSchema, Session))
             )
         query_ = event_query(query_, view_kwargs)
         if view_kwargs.get('speaker_id'):


Test patch: