Skip to content

Commit 36b3f5c

Browse files
authored
[DURACOM-477] Fix slow loading times when caching counts for items (DSpace#12344)
* [CST-25040] make cache count for items in collections/communities Asynch * [CST-25040] fix cache implementation * [CST-25040] fix cache implementation * [DURACOM-477] cleanup
1 parent 485983b commit 36b3f5c

3 files changed

Lines changed: 32 additions & 91 deletions

File tree

dspace-api/src/main/java/org/dspace/browse/ItemCountDAOSolr.java

Lines changed: 30 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -7,121 +7,62 @@
77
*/
88
package org.dspace.browse;
99

10-
import java.util.HashMap;
11-
import java.util.List;
12-
import java.util.Map;
13-
10+
import org.apache.logging.log4j.LogManager;
1411
import org.apache.logging.log4j.Logger;
12+
import org.apache.solr.client.solrj.SolrClient;
13+
import org.apache.solr.client.solrj.SolrQuery;
14+
import org.apache.solr.client.solrj.response.QueryResponse;
1515
import org.dspace.content.Collection;
1616
import org.dspace.content.Community;
1717
import org.dspace.content.DSpaceObject;
1818
import org.dspace.core.Context;
19-
import org.dspace.discovery.DiscoverFacetField;
20-
import org.dspace.discovery.DiscoverQuery;
21-
import org.dspace.discovery.DiscoverResult;
22-
import org.dspace.discovery.DiscoverResult.FacetResult;
23-
import org.dspace.discovery.SearchService;
24-
import org.dspace.discovery.SearchServiceException;
25-
import org.dspace.discovery.configuration.DiscoveryConfigurationParameters;
19+
import org.dspace.discovery.SolrSearchCore;
2620
import org.dspace.discovery.indexobject.IndexableItem;
2721
import org.springframework.beans.factory.annotation.Autowired;
2822

2923
/**
3024
* Discovery (Solr) driver implementing ItemCountDAO interface to look up item
31-
* count information in communities and collections. Caching operations are
32-
* intentionally not implemented because Solr already is our cache.
25+
* count information in communities and collections.
26+
* <p>
27+
* Counts are computed by querying Solr for archived, non-withdrawn, discoverable
28+
* items using {@code location.comm} / {@code location.coll} filters.
29+
* The query returns only {@code numFound} (rows=0), making it very fast.
3330
*/
3431
public class ItemCountDAOSolr implements ItemCountDAO {
35-
/**
36-
* Log4j logger
37-
*/
38-
private static Logger log = org.apache.logging.log4j.LogManager.getLogger(ItemCountDAOSolr.class);
39-
40-
/**
41-
* Hold the communities item count obtained from SOLR after the first query. This only works
42-
* well if the ItemCountDAO lifecycle is bound to the request lifecycle as
43-
* it is now. If we switch to a Spring-based instantiation we should mark
44-
* this bean as prototype
45-
**/
46-
private Map<String, Integer> communitiesCount = null;
47-
48-
/**
49-
* Hold the collection item count obtained from SOLR after the first query
50-
**/
51-
private Map<String, Integer> collectionsCount = null;
5232

33+
private static final Logger log = LogManager.getLogger(ItemCountDAOSolr.class);
5334

54-
/**
55-
* Solr search service
56-
*/
5735
@Autowired
58-
protected SearchService searchService;
36+
private SolrSearchCore solrSearchCore;
5937

60-
/**
61-
* Get the count of the items in the given container.
62-
*
63-
* @param context DSpace context
64-
* @param dso DspaceObject
65-
* @return count
66-
*/
6738
@Override
6839
public int getCount(Context context, DSpaceObject dso) {
69-
loadCount(context);
70-
Integer val = null;
40+
String locationFilter;
7141
if (dso instanceof Collection) {
72-
val = collectionsCount.get(dso.getID().toString());
42+
locationFilter = "location.coll:" + dso.getID().toString();
7343
} else if (dso instanceof Community) {
74-
val = communitiesCount.get(dso.getID().toString());
75-
}
76-
77-
if (val != null) {
78-
return val;
44+
locationFilter = "location.comm:" + dso.getID().toString();
7945
} else {
8046
return 0;
8147
}
82-
}
8348

84-
/**
85-
* make sure that the counts are actually fetched from Solr (if haven't been
86-
* cached in a Map yet)
87-
*
88-
* @param context DSpace Context
89-
*/
90-
private void loadCount(Context context) {
91-
if (communitiesCount != null || collectionsCount != null) {
92-
return;
93-
}
94-
95-
communitiesCount = new HashMap<>();
96-
collectionsCount = new HashMap<>();
97-
98-
DiscoverQuery query = new DiscoverQuery();
99-
query.setFacetMinCount(1);
100-
query.addFacetField(new DiscoverFacetField("location.comm",
101-
DiscoveryConfigurationParameters.TYPE_STANDARD, -1,
102-
DiscoveryConfigurationParameters.SORT.COUNT));
103-
query.addFacetField(new DiscoverFacetField("location.coll",
104-
DiscoveryConfigurationParameters.TYPE_STANDARD, -1,
105-
DiscoveryConfigurationParameters.SORT.COUNT));
106-
query.addFilterQueries("search.resourcetype:" + IndexableItem.TYPE); // count only items
107-
query.addFilterQueries("NOT(discoverable:false)"); // only discoverable
108-
query.addFilterQueries("withdrawn:false"); // only not withdrawn
109-
query.addFilterQueries("archived:true"); // only archived
110-
query.setMaxResults(0);
111-
112-
DiscoverResult sResponse;
11349
try {
114-
sResponse = searchService.search(context, query);
115-
List<FacetResult> commCount = sResponse.getFacetResult("location.comm");
116-
List<FacetResult> collCount = sResponse.getFacetResult("location.coll");
117-
for (FacetResult c : commCount) {
118-
communitiesCount.put(c.getAsFilterQuery(), (int) c.getCount());
119-
}
120-
for (FacetResult c : collCount) {
121-
collectionsCount.put(c.getAsFilterQuery(), (int) c.getCount());
50+
SolrClient solr = solrSearchCore.getSolr();
51+
if (solr == null) {
52+
return 0;
12253
}
123-
} catch (SearchServiceException e) {
124-
log.error("Could not initialize Community/Collection Item Counts from Solr: ", e);
54+
SolrQuery query = new SolrQuery("*:*");
55+
query.addFilterQuery(locationFilter);
56+
query.addFilterQuery("search.resourcetype:" + IndexableItem.TYPE);
57+
query.addFilterQuery("NOT(discoverable:false)");
58+
query.addFilterQuery("withdrawn:false");
59+
query.addFilterQuery("archived:true");
60+
query.setRows(0);
61+
QueryResponse response = solr.query(query, solrSearchCore.REQUEST_METHOD);
62+
return (int) response.getResults().getNumFound();
63+
} catch (Exception e) {
64+
log.error("Error counting items in Solr for {}: ", dso.getID(), e);
12565
}
66+
return 0;
12667
}
12768
}

dspace/config/spring/api/core-services.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
<bean class="org.dspace.authority.AuthorityServiceImpl"/>
3434

3535
<bean class="org.dspace.browse.ItemCounter"/>
36-
<bean id="itemCountDAO" class="org.dspace.browse.ItemCountDAOSolr" scope="prototype"/>
36+
<bean id="itemCountDAO" class="org.dspace.browse.ItemCountDAOSolr"/>
3737

3838
<bean class="org.dspace.checker.ChecksumHistoryServiceImpl"/>
3939
<bean class="org.dspace.checker.ChecksumResultServiceImpl"/>

dspace/solr/search/conf/schema.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@
294294
<field name="location.comm" type="lowerCaseSort" indexed="true" stored="true" multiValued="true" required="false" omitNorms="true" />
295295
<field name="location.coll" type="lowerCaseSort" indexed="true" stored="true" multiValued="true" required="false" omitNorms="true" />
296296
<field name="location.parent" type="lowerCaseSort" indexed="true" stored="true" multiValued="false" required="false" omitNorms="true" />
297-
297+
298298
<field name="a_spell" type="textSpell" />
299299
<copyField source="fulltext" dest="a_spell" />
300300
<copyField source="fulltext" dest="fulltext_hl" />

0 commit comments

Comments
 (0)