Is it possible to see who voted in polls?

I just tested out polls for the first time in a while, and it works quite well and I like it.

But I would like to have an open poll so we can see who voted for which option. Is this possible? Is there any way to see who voted for what?

You can run the following query to get a list of users who voted and their selected poll options.
Please choose the appropriate query for your Discourse version.

Query for Discourse v2.2.0.beta5 and newer

-- [params]
-- post_id :post_id
-- text :poll_name = poll

SELECT u.id AS user_id, u.username, v.poll_option_id AS option_id, o.html AS option_html
FROM polls p
       JOIN poll_votes v ON (p.id = v.poll_id)
       JOIN poll_options o ON (o.id = v.poll_option_id)
       JOIN users u ON (v.user_id = u.id)
WHERE p.post_id = :post_id AND p.name = :poll_name
ORDER BY u.username, v.poll_option_id

Query for older versions of Discourse up to v2.2.0.beta4

-- [params]
-- post_id :post_id
-- text :poll_name = poll

SELECT votes.user_id, users.username, votes.option_id, options.html AS option_html
FROM (
  SELECT value1 ->> 'id' AS id,
    value1 ->> 'html' AS html
  FROM (
    SELECT json_array_elements(value :: JSON -> :poll_name -> 'options') AS value1
    FROM post_custom_fields
    WHERE post_id = :post_id AND name = 'polls' AND value :: JSON -> :poll_name ->> 'name' = :poll_name
  ) option_values
) options
       JOIN (
  SELECT key :: INTEGER AS user_id,
    trim(json_array_elements(value :: JSON -> :poll_name) :: TEXT, '"') AS option_id
  FROM json_each((
    SELECT value :: JSON
    FROM post_custom_fields
    WHERE post_id = :post_id AND name LIKE 'polls-votes'
  ))
) votes ON (options.id = votes.option_id)
       JOIN users ON (votes.user_id = users.id)
ORDER BY users.username, votes.option_id

How to find post_id

You can use the following query if you need to find the right post_id.

-- [params]
-- topic_id :topic_id
-- int :post_number = 1

SELECT id
FROM posts
WHERE topic_id = :topic_id AND post_number = :post_number

it works! thanks so much. :fireworks:

is there a query for quickly identifying the post ID containing polls? I used the .json URL method but it was surprisingly cumbersome to find the right post within it.

Default values are specified like this:

I updated the query. It’s now a lot simpler. :slight_smile:

Existe-t-il un moyen de filtrer les résultats en fonction de l’ancienneté du compte ?

Par exemple, si un compte a moins de 60 jours, il ne devrait pas apparaître dans les résultats ? Ou peut-être existe-t-il un moyen de créer un sondage qui limite les votes en fonction de l’ancienneté du compte ?

Nous tentons d’empêcher tout bourrage d’urne par des comptes récemment créés pour un vote important à venir.

C’est un cas d’usage très intéressant. Je pense que nous devrions avoir une option pour empêcher les utilisateurs TL0 de voter dans un sondage @zogstrip !

Existe-t-il un paramètre que je pourrais ajouter à la chaîne de recherche de @gerhard pour exclure les utilisateurs dont le niveau de confiance ou l’ancienneté du compte est inférieur à une certaine valeur dans la requête ?

Même si je devais compter manuellement les votes sur la base des résultats, ce serait plus rapide que de vérifier manuellement l’âge de chaque compte et leurs votes.

Voici une requête pour définir un niveau de confiance minimal pour les utilisateurs.

-- [params]
-- post_id :post_id
-- text :poll_name = poll
-- integer :min_trust_level

SELECT u.id AS user_id, u.username, v.poll_option_id AS option_id, o.html AS option_html
FROM polls p
       JOIN poll_votes v ON (p.id = v.poll_id)
       JOIN poll_options o ON (o.id = v.poll_option_id)
       JOIN users u ON (v.user_id = u.id)
WHERE p.post_id = :post_id AND p.name = :poll_name
  AND u.trust_level >= :min_trust_level
ORDER BY u.username, v.poll_option_id

Et voici une requête pour afficher uniquement les utilisateurs inscrits depuis un certain nombre de jours.

-- [params]
-- post_id :post_id
-- text :poll_name = poll
-- integer :days_ago = 30

SELECT u.id AS user_id, u.username, v.poll_option_id AS option_id, o.html AS option_html
FROM polls p
       JOIN poll_votes v ON (p.id = v.poll_id)
       JOIN poll_options o ON (o.id = v.poll_option_id)
       JOIN users u ON (v.user_id = u.id)
WHERE p.post_id = :post_id AND p.name = :poll_name
  AND u.created_at < NOW() - INTERVAL ':days_ago days' 
ORDER BY u.username, v.poll_option_id

Super :heart_eyes: @gerhard merci !

Notez que cette requête est désormais incluse dans les requêtes Data Explorer par défaut qui sont installées automatiquement, vous n’avez donc pas besoin de saisir ce code vous-même !

Une autre façon de trouver l’ID d’un message, surtout s’il s’agit du premier message, consiste à consulter <topic_url>.json (par exemple, Is it possible to see who voted in polls?). Il est assez facile de trouver l’ID du message au début de ce fichier JSON.

@nbianca peux-tu ajouter à ta liste un nouveau paramètre de sondage min_trust_level qui permettra aux créateurs de sondages de restreindre le vote en fonction du niveau de confiance des utilisateurs ?

Cette option doit être disponible dans l’interface du créateur de sondages, et un message clair doit expliquer pourquoi certains utilisateurs ne peuvent pas voter sur ce sondage.

Vous n’avez même pas besoin de trouver l’ID du message, car un bouton d’exportation est désormais disponible dans les sondages pour les membres du personnel.

Cela a été implémenté, mais légèrement différemment de ce qui était demandé. Les sondages acceptent une option groups et non min_trust_level. Cette option accepte une liste de noms de groupes séparés par des virgules (par exemple trust_level_2,staff pour autoriser les niveaux de confiance 2 et supérieurs ainsi que tous les membres du personnel).

Je suis désolé, mais c’est trop confus pour moi. Pouvez-vous me l’expliquer plus simplement ?