Come creare un'unione di due viste?


36

Sto cercando di ottenere un'unione dei nodi e dei commenti di un utente ordinati per "data post". Questo post si collega a progetti sandbox per D6 ma non c'è nulla per 7.

Questo post contiene un esempio dell'utilizzo di hook_views_pre_execute () e di un SQL UNION in D6. Questo non funziona con D7 con viste 3.

Mi sono imbattuto nel commento di Merlinofchaos

Poiché ora stiamo utilizzando il nuovo generatore di query di Drupal, la query è un oggetto SelectQuery che dovrai modificare o sostituire. Cerca il nuovo livello di database di Drupal 7 per ulteriori informazioni.

Qualcuno ha un esempio di come fare questa o un'altra soluzione per combinare due viste?


questa è più un'idea che una vera risposta: dovresti essere in grado di creare una vista basata sugli utenti, che dovrebbe unire sia i nodi che i commenti (non sono entrambi entità dopo tutto :). Al mio primo tentativo non sono riuscito a farlo perché le viste non offrono la relazione da utente a commento. Ma dovrebbe essere facile da modificare. (o ho appena dimenticato qualcosa).
Mojzis,

Penso che sia la stessa risposta di seguito: kt richiederebbe due filtri contestuali (content.author = utente registrato O comment.author = utente connesso).
Uwe

non credo :) intendo una vista basata sugli utenti, che unisce i nodi e i commenti. ma ho la sensazione che ci sia qualche problema con la relazione tra utente e commento - non sono riuscito a mostrare i commenti.
Mojzis,

Sto solo indovinando, ma non puoi usare searchapi per indicizzare più tipi di entità contemporaneamente? Una volta che lo hai e hai un campo che viene utilizzato da entrambe le parti, puoi usarlo per creare una vista del genere.
Daniel Wehner,

1
Esiste un progetto sandbox "Views Unionize" per drupal 7, si prega di controllare drupal.org/sandbox/jalama/1785294 ,
Anoop Joseph,

Risposte:


15

Ecco un esempio funzionante e testato:

/**
 * Implements hook_views_pre_execute().
 */
function mymodule_views_pre_execute(view &$view) {
  if ($view->name == 'my_view') {
    $query1 = &$view->build_info['query'];

    // Basic setup of the second query.
    $query2 = db_select('another_table', 'at')
      ->condition('some_field', 0, '>')
      ->condition('some_other_field', 12345);

    // The number of fields (and their aliases) must match query1.
    // Get the details with:
    // dpm($query1->getFields());
    $query2->addField('at', 'some_field', 'alias1');
    $query2->addField('at', 'some_other_field', 'alias2');
    $query2->addField('at', 'some_other_field2', 'alias3');
    $query2->addField('at', 'some_other_field3', 'alias4');

    // Verify that queries are very similar.
    // dpq($query1);
    // dpq($query2);

    // Matrimony.
    $query1 = $query2->union($query1, 'UNION ALL');

    // Manual test.
    // dpm($query1->execute()->fetchAll());

  }
}

Questo funziona per la maggior parte delle visualizzazioni. Tuttavia alcuni plugin di stile possono fare cose fantasiose che non funzioneranno con questa tecnica (modulo Calendar ti sto guardando).



2

Ho finito per usare db_query () per creare le UNION SQL e poi renderlo in un layout di tabella includendo i cercapersone usando la funzione theme ().

All'utente sembrano visualizzazioni predefinite. L'altro vantaggio era che potevo ottimizzare molto la query. Sto mostrando "le attività del mio amico" e se tu usassi le viste per questo creerebbe un elenco dei tuoi amici e lo userebbe in una clausola SQL "IN" che è molto lenta se hai più di 50 o 100 record.

Potrei restringere quell'elenco di amici solo a quelli che sono stati registrati nel sito negli ultimi x giorni.

Questo è un esempio di codice:

  // Two queries are required (friendships can be represented in 2 ways in the
  // same table). No point making two db calls though so a UNION it is.

  // Build up the first query.
  $query = db_select('flag_friend', 'f')
    ->condition('f.uid', $account->uid)
    ->condition('u.login', $timestamp, '>');
  $query->addExpression('f.friend_uid', 'uid');
  $query->innerJoin('users', 'u', 'u.uid = f.friend_uid');

  // Build up the second query.
  $query2 = db_select('flag_friend', 'f')
    ->condition('f.friend_uid', $account->uid)
    ->condition('u.login', $timestamp, '>');
  $query2->addExpression('f.uid', 'uid');
  $query2->innerJoin('users', 'u', 'u.uid = f.uid');

  // Return the results of the UNIONed queries.
  return $query->union($query2)->execute()->fetchCol();

1

Per riferimento futuro, è così che ho combinato due viste basate sulla stessa tabella insieme. Gli stessi principi dovrebbero applicarsi anche alle viste basate su tabelle diverse con lo stesso numero di campi.

Nel caso seguente viene selezionato solo id poiché il formato è impostato su entità renderizzata. Ma se stai andando con i campi puoi sempre aggiungere ulteriori campi fittizi alla query che ha meno campi come ho aggiunto il timestamp di seguito.

/**
 * Implements hook_views_pre_execute().
 */
function MY_MODULE_views_pre_execute(&$view) {
  if ($view->name == 'VIEW_1' && $view->current_display == 'DISPLAY_OF_VIEW_1') {

    $view2 = views_get_view('VIEW_2');
    $view2->build('DISPLAY_OF_VIEW_2');

    $view->build_info['query']
    ->fields('table_alias', array('timestamp'))
    ->union(
        $view2->build_info['query']
        ->range()
        ->fields('table_alias', array('timestamp'))
        ->orderBy('timestamp', 'DESC')
    );

    $view->build_info['count_query']
    ->union(
        $view2->build_info['count_query']
        ->range()
    );
  };
}

0

Immagino che sia qualcosa del genere:

/** 
* Implements hook_views_pre_execute().
*/     
function mymodule_views_pre_execute(&$view) {
  if ($view->name == 'myview') {
    $query = $view->query;
    $other_view = views_get_view('otherview');
    $other_query = $other_view->query;
    $query = $query->union($other_query);
    $view->query = $query;
  }
}

Anche se non l'ho provato.

Alcuni link che possono aiutare:

http://api.drupal.org/api/drupal/includes!database!select.inc/function/SelectQueryInterface%3A%3Aunion/7

http://drupal.org/node/557318#comment-1991910


1
Questo non sembra funzionare completamente. $ view-> query è l'oggetto intermedio che Views utilizza per creare la query. SelectQuery è $ view-> build_info ['query']. Quando modifichi di conseguenza, non riesco ad andare oltre l'errore "Errore irreversibile: chiamata al metodo indefinito SelectQuery :: render_pager ()".
mpdonadio

1
Il codice di test del database contiene esempi di sindacati api.drupal.org/api/drupal/… e api.drupal.org/api/drupal/…
mikeytown2


L'unico modo in cui ciò potrebbe funzionare è se entrambe le viste sono quasi identiche.
Dalin,

0

Mi sono imbattuto in un modulo chiamato Views Field View , che consente di incorporare una vista come campo in un'altra vista. Non l'ho ancora provato io stesso, ma potrebbe esserti utile.


2
Mentre Views Field View può effettivamente ottenere sia commenti che nodi, non credo che ci sia un modo per ordinare attraverso i campi, solo all'interno di essi.
Letharion,

0

Il back-end EntityFieldQuery Views supporta l'interrogazione per più tipi di entità contemporaneamente. Quindi dovrebbe essere utilizzabile eseguire query per nodi e commenti. Entrambi i tipi di entità utilizzano una uidproprietà per collegarsi al proprio autore, quindi a livello di API EntityFieldQuery :: propertyCondition () dovrebbe essere utilizzabile per selezionare i nodi e i commenti da un singolo utente. Immagino che il backend delle viste offra la stessa funzionalità.


sembra che abbiano appena rimosso la funzione per interrogare più entità: drupal.org/node/1564740
uwe

0

Un approccio diverso potrebbe essere quello di creare feed di nodi e commenti (con un filtro contestuale dell'identificatore dell'utente nell'URL) e quindi combinare i due feed in un nuovo feed e visualizzarlo per data di pubblicazione.


-2

Usato globale: campi PHP ? Puoi usarli per canalizzare insieme un nastro in una Vista che combina i due.

Crea una vista del contenuto con i campi Contenuto: Titolo e Contenuto: Commenti (esclusi dalla visualizzazione).

Aggiungi un campo PHP che calcoli quale è più recente, la data dell'ultimo aggiornamento o la data dell'ultimo commento dell'utente e imposta il valore del campo su quella data. Aggiungi quel campo come condizione di ordinamento.

Aggiungi un campo simile che genera un collegamento al commento o al nodo.

Mi suona bene!


idea interessante. Richiederebbe due filtri contestuali (content.author = utente registrato O comment.author = utente connesso).
Uwe

Spero di ottenere l'epica ripresa su questo ...;)
Johnathan Elmore il

2
Il successo prestazionale di questo approccio sarebbe spaventoso. Il numero potenziale di query di database eseguite potrebbe andare oltre l'astronomia.
Rider_X,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.