3

I want to query last 5 nodes of multiple content types, say, typeA, typeB, typeC, typeD.

It was originally only one content type, and I did it using EntityFieldQuery:

$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'typeA')
  ->propertyCondition('status', 1)
  ->propertyOrderBy('created', 'DESC')
  ->range(0, 5);

$result = $query->execute();

But now I need to include 3 other content types to the list.

Is there any way to expend this query to include the last 5 nodes of the other 3 content types as well. So that the result will have 5 last nodes from all 4 content types, altogether 20 nodes.

Or should I do it with 4 individual queries?

6
  • 3
    Probably easiest to do it with 4 individual queries.
    – Beebee
    Sep 24, 2014 at 15:18
  • 1
    Yeah I guess probably we have to run the same query 4 times (running query inside foreach loop, as only the content type is going to rest and rest everything is as it is) in order to get the desired result. Sep 24, 2014 at 15:25
  • 1
    Yeah you'll need 4 different queries here, whether you roll them all into one with sub-queries or not. Definitely can't do it with EFQ (unless you alter the query), it wouldn't be able to express the necessary grouping
    – Clive
    Sep 24, 2014 at 15:37
  • I guess you can give a try to union once if you want to do it with the single query. Sep 24, 2014 at 15:39
  • Thanks, for your comments. Then, I'll do it with 4 individual queries. @Clive, should I keep this question or delete it? Seemingly there is no way other than what I already proposed in my question. Sep 24, 2014 at 16:04

5 Answers 5

2

I think the only thing you need is alter the second line of your EntityFieldQuery to this:

->entityCondition('bundle', array('typeA', 'typeB', 'typeC', 'typeD'), 'IN')

Haven't tested this particular though, but you can query multiple content types this way.

Cheers

EDIT: Maybe this can help you more: https://www.drupal.org/node/2048345

4
  • No, I want to get exactly 5 nodes from each type. Your suggestion would return 5 nodes of any given types, Apr 11, 2016 at 14:13
  • Maybe this can help you then! drupal.org/node/2048345
    – geodoo
    Apr 12, 2016 at 16:29
  • That seems interesting. I didn't think about UNION. I'll give it a try as soon as I get the time for it. Thanks. Please edit your answer and add this link with a short description. After I try it, I'll give you a feedback. Apr 13, 2016 at 7:11
  • Hey Adrian, I really don't have the time to add short description because this is not my case and I haven't tried that. I bounced in this question for querying multiple content types only. Not exactly your case. But I will add the link to my answer as proposed by you! Again, cheers!
    – geodoo
    Apr 14, 2016 at 7:35
1

Try something like the following codes:

$types= array('type1','type2','type3');

foreach ($types as $type) {
  $query->entityCondition('entity_type', 'node')
    ->entityCondition('bundle', 'typeA')
    ->propertyCondition('status', 1)
    ->propertyOrderBy('created', 'DESC')
    ->range(0, 5);
  $temp = $query->execute();

  if (isset($temp['node'])) {
    $result[$type]['nids'] = array_keys($temp['node']); 
    $result[$type]['nodes'] = node_load_multiple($result[$type]['nids']);
  } 
}

/// then you can load them by 
0

I think as other have suggested using UNION is going to be the easiest way to do it with one query:

$nids = db_query("(SELECT nid FROM node WHERE type = 'typeA' ORDER BY changed LIMIT 0, 5)
UNION
(SELECT nid FROM node WHERE type = 'typeB' ORDER BY changed LIMIT 0, 5)
UNION
(SELECT nid FROM node WHERE type = 'typeC' ORDER BY changed LIMIT 0, 5)
UNION
(SELECT nid FROM node WHERE type = 'typeD' ORDER BY changed LIMIT 0, 5)")->fetchCol();
$nodes = node_load_multiple($nids);

I was playing with a way to do it using numbered rows but it doesn't get the latest nodes so I gave up, but here is the sql in case your interested in fixing it:

SELECT nid, title, type, changed
FROM (
    SELECT nid, title, type, changed,
    @num := if(@group = type, @num + 1, 1) as row_number,
    @group := type as dummy
    FROM   node
    WHERE type IN ('typeA', 'typeB', 'typeC', 'typeD')
    ORDER BY type, title
) AS x
WHERE  row_number <= 5
ORDER BY type

Also see this very relevant SO question MySQL:How to get n latest rows of a distinct type

-1

the best way you can do it is to user db_select(); I would do something like this:

Set the array with the content type machine names.

$arrayofnodetypes = array('page','post','poll');

here you select the table

$query = db_select('node','n'); 
$query->fields('n',array('nid','title','status','type')); // this are the fields your want to fetch
$query->condition('n.status','1','='); // node is published
$query->condition('n.type',$arrayofnodetypes,'IN'); // this is where you call the content types.
$query->orderBy('created','DESC');
$query->range(0,20);

$results = $query->execute()->fetchAll();

Then you have 2 options.

the first:
if you want to fetch all fields in the node, you need to manualy join the fields in the $query see the following resource if you want to learn more: https://www.drupal.org/node/1848348

the second: the $results variable will have the results of the query.

I would then foreach each result of the array.

like the folowing;

$nodes = array();
foreach($results as $item) {
  $nodes []= node_load($item->nid);
}

then the $nodes array will contain the results you need.

3
  • Thanks for your attempt, however this way I won't get 5 nodes from each content type, but 20 nodes, which can also be from the same type.. I need explicitly 5 from each content type. Sep 24, 2014 at 16:37
  • that's easy create 5 queries and mix the results in an array. Sep 24, 2014 at 16:45
  • That was already what I proposed in my question. I've asked if there were any other way to do it using only one query. Seemingly there isn't. Sep 24, 2014 at 16:47
-1

You could also use node_load_multiple.

$types = array('content_type_1', 'content_type_2', 'etc');
$query = db_select('node', 'n')
  ->fields('n', array('nid'))
  ->condition('type', $type, 'IN');

$result = $query->execute()->fetchAll();

$nids = array(); foreach ($result as $row) { $nids[] = $row->nid; }

$nodes = node_load_multiple($nids);

1
  • This is not the result I wanted to reach. I wanted to get exactly 5 nodes from each content type. Your solution doesn't provide that. Dec 28, 2015 at 9:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.