I created a view with flag as relationship. This causes nodes to appear more than once. I added distinct and also the only fields I added were Flag link and Flag count. Even though I removed the two fields with out removing the relationship, the rows are repeating how many time that particular node is flagged. If I flagged a node 3 time the node is appearing thrice.

Also "Node flag counter" relationship mentioned in the below link is not available in Drupal 8
https://www.drupal.org/node/922986

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

sumithb created an issue. See original summary.

joachim’s picture

Issue tags: -Flag, -duplicate, -views

How many flags do you have? Did you filter by them?

(BTW: please don't use random tags!)

sumithb’s picture

Hi joachim,

Thanks for looking into this.

I am using only one flag: Like. Added relationship with this Like flag selected.

joachim’s picture

Can you post the config output of your view please?

kpv’s picture

The duplicates appear when "Any user" is chosen in flag relationship settings for "By" option. If "Current user" chosen, duplicates don't appear though you can't get total flags count then.

joachim’s picture

Status: Active » Closed (works as designed)

Thanks for the explanation!

In which case, this is as designed. If you join nodes to flaggings, and the flag is non-global, then you will get repeated rows because there will be more than one flagging for each node.

kpv’s picture

Status: Closed (works as designed) » Active

Then we should allow to join on flag_counts table.
Now user can use flagging relationship and it would work with DISTINCT if the view wouldn't add {flagging}.id field (which is not used) to the query.

Shortly, the following case should be available: output a list of entities with total number of flags (of one type) on it. E.g. you want to make a list of popular nodes and show how many users flagged it.

alanburke’s picture

> E.g. you want to make a list of popular nodes and show how many users flagged it.
Yep - exactly the use case I'm aiming for.
Happy to try write a patch, if some advice can be given as to where to start

joachim’s picture

> Happy to try write a patch, if some advice can be given as to where to start

> Then we should allow to join on flag_counts table.

That sounds like the right approach. Though I've a feeling there is already an issue for this -- please check before uploading a patch to this one!

The steps would be:

- find where we declared Views data. Might be the hook, or might be an entity views data handler for the flagging entity
- declare flag_counts table if not already done
- iterate over all flags
- for each different entity type that has a flag on it, add a relationship to that entity type's base table that joins to flag_counts on the entity ID and entity type (the entity type needs to be in a join extra property in the views data)
- add a views relationship handler plugin, which has:
-- setting for to let you pick the flag
-- query() method which restricts the join by the flag
- add a field to the flag_counts table for the count

attheshow’s picture

Hey, I just wanted to share a workaround I did for our site. Inside a custom module I added an implementation of hook_views_query_alter() with a group by like this:

use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\query\QueryPluginBase;

/**
 * Implements hook_views_query_alter().
 */
function YOURMODULE_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
  if ($view->id() == 'YOURVIEWID' && $view->current_display == 'YOURDISPLAY') {
    $query->addField('node', 'nid', 'node_nid', array('function' => 'groupby'));
    $query->addGroupBy('node.nid');
  }
}
droprocker’s picture

Any news about this issue?

kpv’s picture

@attheshow, thanks for sharing

Mike Lewis’s picture

I took attheshow's idea and created a hook_views_query_alter implementation in the flag.module file itself that applies that group by to the base_table.base_field for the view whenever a flag relationship is present and the count is being output.

It's possible this could use some refinement, but here's the patch:

Mike Lewis’s picture

Status: Active » Needs review
AvO WebWorks’s picture

Patch #13 works and fixes the issue. Thank you

KlemenDEV’s picture

Is there anyone who could get this patch in next release?

joachim’s picture

Status: Needs review » Needs work
+++ b/flag.module
@@ -115,6 +116,18 @@ function flag_help($route_name, RouteMatchInterface $route_match) {
+  if (!empty($view->relationship) && is_array($view->relationship) && isset($view->relationship['flag_relationship']) && isset($view->field['count'])) {

We're testing for a relationship handler that we provide.

So we should be able to make this query alteration in the handler itself, rather than use a hook.

KlemenDEV’s picture

Thank you for the info. I hope this gets forward soon :)

ydahi’s picture

+1 rtbc for patch #13 on 8.x-4.0-alpha3

joachim’s picture

Please see my comment in #17 -- the patch needs work.

ccshannon’s picture

I have the same "duplicates" issue using a flag called "Follow" on a single node type, to sort by "most followed" descending. I tried the patch in #17, but it did not result in the desired outcome. The solution in #10 did, however, provide the desired outcome. Thanks, @attheshow!

MykolaVeryha’s picture

We can use unique index. It will resolve the bug

function hook_update_8701() {
  // Remove duplicates to avoid exception during creating unique index.
  /** @var \Drupal\flag\Entity\Storage\FlaggingStorageInterface $flagging_storage */
  $flagging_storage = Drupal::entityTypeManager()->getStorage('flagging');
  $flaggings_values = $flagging_storage->getAggregateQuery()
    ->groupBy('id')
    ->groupBy('uid')
    ->groupBy('entity_id')
    ->groupBy('flag_id')
    ->execute();

  $exists_flaggings = [];
  foreach ($flaggings_values as $flagging_values) {
    $key = $flagging_values['uid'] . $flagging_values['entity_id'] . $flagging_values['flag_id'];
    if (isset($exists_flaggings[$key])) {
      $flagging_storage->load($flagging_values['id'])->delete();
    }
    else {
      $exists_flaggings[$key] = $key;
    }
  }

  if (Drupal::database()->schema()->indexExists('flagging', 'unique_flag')) {
    Drupal::database()->schema()->dropIndex('flagging', 'unique_flag');
  }
  Drupal::database()->query(
    'ALTER TABLE `flagging` ADD UNIQUE `unique_flag` (`uid`, `flag_id`(30), `entity_id`(40)) USING BTREE;'
  );
}
cryptoline’s picture

cryptoline’s picture

Greetings, the patch given above is not working. How can I solve this problem?

chucksimply’s picture

Patch isn't working on my end anymore. Any updates?

chucksimply’s picture

@attheshow's solution on #10 does work for me as a custom module. Can we not get this as a workable patch? Seems as though #13 isn't cutting it?

Anonymous’s picture

Any news on this?

holybiber’s picture

Maybe I'm missing something obvious, but I solved this problem by just enabling "Use aggregation" in the advanced settings of the view. That way I only get one row per node and still can query the flag count.

KlemenDEV’s picture

This does not work with content types with images due to a bug in views, and could also be considered a workaround, not a solution.

tunaman’s picture

I used https://www.drupal.org/project/issues/views_distinct to solve that problem (filtering by NID). You'll need to patch it to get a D9/10 version though.