use of org.alfresco.repo.domain.node.Node in project alfresco-repository by Alfresco.
the class DbOrIndexSwitchingQueryLanguage method executeHybridQuery.
private ResultSet executeHybridQuery(SearchParameters searchParameters) {
if (indexQueryLanguage == null || dbQueryLanguage == null) {
throw new QueryModelException("Both index and DB query language required for hybrid search [index=" + indexQueryLanguage + ", DB=" + dbQueryLanguage + "]");
}
StopWatch stopWatch = new StopWatch("hybrid search");
if (logger.isDebugEnabled()) {
logger.debug("Hybrid search, using SOLR query: " + dbQueryLanguage.getName() + " for " + searchParameters);
}
stopWatch.start("index query");
ResultSet indexResults = indexQueryLanguage.executeQuery(searchParameters);
stopWatch.stop();
if (logger.isDebugEnabled()) {
logger.debug("SOLR query returned " + indexResults.length() + " results in " + stopWatch.getLastTaskTimeMillis() + "ms");
}
if (!(indexResults instanceof SolrJSONResultSet)) {
if (logger.isWarnEnabled()) {
logger.warn("Hybrid search can only use database when SOLR is also in use. " + "Skipping DB search, returning results from index.");
}
return indexResults;
}
long lastTxId = ((SolrJSONResultSet) indexResults).getLastIndexedTxId();
searchParameters.setSinceTxId(lastTxId);
if (logger.isDebugEnabled()) {
logger.debug("Hybrid search, using DB query: " + dbQueryLanguage.getName() + " for " + searchParameters);
}
stopWatch.start("database query");
ResultSet dbResults = dbQueryLanguage.executeQuery(searchParameters);
stopWatch.stop();
if (logger.isDebugEnabled()) {
logger.debug("DB query returned " + dbResults.length() + " results in " + stopWatch.getLastTaskTimeMillis() + "ms");
}
// Merge result sets
List<ChildAssociationRef> childAssocs = new ArrayList<>();
NodeParameters nodeParameters = new NodeParameters();
nodeParameters.setFromTxnId(lastTxId + 1);
// TODO: setToTxnId(null) when SolrDAO behaviour is fixed.
nodeParameters.setToTxnId(Long.MAX_VALUE);
stopWatch.start("get changed nodes");
List<Node> changedNodeList = solrDao.getNodes(nodeParameters, null, null);
stopWatch.stop();
if (logger.isDebugEnabled()) {
logger.debug("Nodes changed since last indexed transaction (ID " + lastTxId + ") = " + changedNodeList.size() + " (took " + stopWatch.getLastTaskTimeMillis() + "ms)");
}
stopWatch.start("merge result sets");
Set<NodeRef> nodeRefs = new HashSet<>(changedNodeList.size());
for (Node n : changedNodeList) {
nodeRefs.add(n.getNodeRef());
}
// Only use the SOLR results for nodes that haven't changed since indexing.
for (ChildAssociationRef car : indexResults.getChildAssocRefs()) {
if (!nodeRefs.contains(car.getChildRef())) {
childAssocs.add(car);
}
}
// Merge in all the database results.
childAssocs.addAll(dbResults.getChildAssocRefs());
ResultSet results = new ChildAssocRefResultSet(nodeService, childAssocs);
// merge result sets
stopWatch.stop();
if (logger.isDebugEnabled()) {
String stats = String.format("SOLR=%d, DB=%d, total=%d", indexResults.length(), dbResults.length(), results.length());
logger.debug("Hybrid search returning combined results with counts: " + stats);
logger.debug(stopWatch.prettyPrint());
}
return results;
}
use of org.alfresco.repo.domain.node.Node in project alfresco-repository by Alfresco.
the class SOLRTrackingComponentImpl method getNodes.
/**
* {@inheritDoc}
*/
public void getNodes(NodeParameters nodeParameters, NodeQueryCallback callback) {
if (enabled) {
QName shardPropertQName = null;
QName shardPropertyType = null;
if (nodeParameters.getShardProperty() != null) {
PropertyDefinition pdef = QueryParserUtils.matchPropertyDefinition(NamespaceService.CONTENT_MODEL_1_0_URI, namespaceService, dictionaryService, nodeParameters.getShardProperty());
if (pdef == null) {
logger.warn("Invalid shard property: " + nodeParameters.getShardProperty());
} else {
shardPropertyType = pdef.getDataType().getName();
if (!shardPropertyType.equals(DataTypeDefinition.TEXT) && !shardPropertyType.equals(DataTypeDefinition.DATE) && !shardPropertyType.equals(DataTypeDefinition.DATETIME) && !shardPropertyType.equals(DataTypeDefinition.INT) && !shardPropertyType.equals(DataTypeDefinition.LONG)) {
logger.warn("Unsupported shard property type: " + (pdef.getDataType().getName() + " for " + nodeParameters.getShardProperty()));
} else {
shardPropertQName = pdef.getName();
}
}
}
List<Node> nodes = solrDAO.getNodes(nodeParameters, shardPropertQName, shardPropertyType);
for (Node node : nodes) {
if (shardRegistry != null) {
shardRegistry.getShardInstanceByTransactionTimestamp(nodeParameters.getCoreName(), node.getTransaction().getCommitTimeMs()).ifPresent(shardId -> ((NodeEntity) node).setExplicitShardId(shardId));
}
callback.handleNode(node);
}
}
}
use of org.alfresco.repo.domain.node.Node in project alfresco-repository by Alfresco.
the class SOLRDAOTest method testGetNodesForTxnRange.
public void testGetNodesForTxnRange() {
List<Transaction> txns = getTransactions(null, null, null, null, 500);
List<Long> txnIds = toTxnIds(txns);
// Only works if there are transactions
if (txnIds.size() < 2) {
// Nothing to test
return;
}
NodeParameters nodeParameters = new NodeParameters();
nodeParameters.setFromTxnId(txnIds.get(0));
nodeParameters.setToTxnId(txnIds.get(1));
List<Node> nodes = getNodes(nodeParameters);
assertTrue("Expect 'some' nodes associated with txns", nodes.size() > 0);
}
use of org.alfresco.repo.domain.node.Node in project alfresco-repository by Alfresco.
the class NodeServiceTest method testCaches_ImmutableNodeCaches.
/**
* Check that simple node property modifications advance the node caches correctly
*/
@SuppressWarnings("unchecked")
@Test
public void testCaches_ImmutableNodeCaches() throws Exception {
final NodeRef[] nodeRefs = new NodeRef[2];
final NodeRef workspaceRootNodeRef = nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
buildNodeHierarchy(workspaceRootNodeRef, nodeRefs);
final NodeRef nodeRef = nodeRefs[1];
// Get the current node cache key
Long nodeId = (Long) findCacheValue(nodesCache, nodeRef);
assertNotNull("Node not found in cache", nodeId);
Node nodeOne = (Node) findCacheValue(nodesCache, nodeId);
assertNotNull("Node not found in cache", nodeOne);
NodeVersionKey nodeKeyOne = nodeOne.getNodeVersionKey();
// Get the node cached values
Map<QName, Serializable> nodePropsOne = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeyOne);
Set<QName> nodeAspectsOne = (Set<QName>) findCacheValue(aspectsCache, nodeKeyOne);
// Check the values
assertEquals("The node version is incorrect", Long.valueOf(1L), nodeKeyOne.getVersion());
assertNotNull("No cache entry for properties", nodePropsOne);
assertNotNull("No cache entry for aspects", nodeAspectsOne);
assertEquals("Property count incorrect", 1, nodePropsOne.size());
assertNotNull("Expected a cm:name property", nodePropsOne.get(ContentModel.PROP_NAME));
assertEquals("Aspect count incorrect", 1, nodeAspectsOne.size());
assertTrue("Expected a cm:auditable aspect", nodeAspectsOne.contains(ContentModel.ASPECT_AUDITABLE));
// Add a property
nodeService.setProperty(nodeRef, PROP_RESIDUAL, GUID.generate());
// Get the values for the previous version
Map<QName, Serializable> nodePropsOneCheck = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeyOne);
Set<QName> nodeAspectsOneCheck = (Set<QName>) findCacheValue(aspectsCache, nodeKeyOne);
assertTrue("Previous cache entries must be left alone", nodePropsOneCheck.equals(nodePropsOne));
assertTrue("Previous cache entries must be left alone", nodeAspectsOneCheck.equals(nodeAspectsOne));
// Get the current node cache key
Node nodeTwo = (Node) findCacheValue(nodesCache, nodeId);
assertNotNull("Node not found in cache", nodeTwo);
NodeVersionKey nodeKeyTwo = nodeTwo.getNodeVersionKey();
// Get the node cached values
Map<QName, Serializable> nodePropsTwo = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeyTwo);
Set<QName> nodeAspectsTwo = (Set<QName>) findCacheValue(aspectsCache, nodeKeyTwo);
// Check the values
assertEquals("The node version is incorrect", Long.valueOf(2L), nodeKeyTwo.getVersion());
assertNotNull("No cache entry for properties", nodePropsTwo);
assertNotNull("No cache entry for aspects", nodeAspectsTwo);
assertFalse("Properties must have moved on", nodePropsTwo.equals(nodePropsOne));
assertEquals("Property count incorrect", 2, nodePropsTwo.size());
assertNotNull("Expected a cm:name property", nodePropsTwo.get(ContentModel.PROP_NAME));
assertNotNull("Expected a residual property", nodePropsTwo.get(PROP_RESIDUAL));
assertTrue("Aspects must be carried", nodeAspectsTwo.equals(nodeAspectsOne));
// Remove a property
nodeService.removeProperty(nodeRef, PROP_RESIDUAL);
// Get the values for the previous version
Map<QName, Serializable> nodePropsTwoCheck = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeyTwo);
Set<QName> nodeAspectsTwoCheck = (Set<QName>) findCacheValue(aspectsCache, nodeKeyTwo);
assertTrue("Previous cache entries must be left alone", nodePropsTwoCheck.equals(nodePropsTwo));
assertTrue("Previous cache entries must be left alone", nodeAspectsTwoCheck.equals(nodeAspectsTwo));
// Get the current node cache key
Node nodeThree = (Node) findCacheValue(nodesCache, nodeId);
assertNotNull("Node not found in cache", nodeThree);
NodeVersionKey nodeKeyThree = nodeThree.getNodeVersionKey();
// Get the node cached values
Map<QName, Serializable> nodePropsThree = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeyThree);
Set<QName> nodeAspectsThree = (Set<QName>) findCacheValue(aspectsCache, nodeKeyThree);
// Check the values
assertEquals("The node version is incorrect", Long.valueOf(3L), nodeKeyThree.getVersion());
assertNotNull("No cache entry for properties", nodePropsThree);
assertNotNull("No cache entry for aspects", nodeAspectsThree);
assertFalse("Properties must have moved on", nodePropsThree.equals(nodePropsTwo));
assertEquals("Property count incorrect", 1, nodePropsThree.size());
assertNotNull("Expected a cm:name property", nodePropsThree.get(ContentModel.PROP_NAME));
assertNull("Expected no residual property", nodePropsThree.get(PROP_RESIDUAL));
assertTrue("Aspects must be carried", nodeAspectsThree.equals(nodeAspectsTwo));
// Add an aspect
nodeService.addAspect(nodeRef, ContentModel.ASPECT_TITLED, null);
// Get the values for the previous version
Map<QName, Serializable> nodePropsThreeCheck = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeyThree);
Set<QName> nodeAspectsThreeCheck = (Set<QName>) findCacheValue(aspectsCache, nodeKeyThree);
assertTrue("Previous cache entries must be left alone", nodePropsThreeCheck.equals(nodePropsThree));
assertTrue("Previous cache entries must be left alone", nodeAspectsThreeCheck.equals(nodeAspectsThree));
// Get the current node cache key
Node nodeFour = (Node) findCacheValue(nodesCache, nodeId);
assertNotNull("Node not found in cache", nodeFour);
NodeVersionKey nodeKeyFour = nodeFour.getNodeVersionKey();
// Get the node cached values
Map<QName, Serializable> nodePropsFour = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeyFour);
Set<QName> nodeAspectsFour = (Set<QName>) findCacheValue(aspectsCache, nodeKeyFour);
// Check the values
assertEquals("The node version is incorrect", Long.valueOf(4L), nodeKeyFour.getVersion());
assertNotNull("No cache entry for properties", nodePropsFour);
assertNotNull("No cache entry for aspects", nodeAspectsFour);
assertTrue("Properties must be carried", nodePropsFour.equals(nodePropsThree));
assertFalse("Aspects must have moved on", nodeAspectsFour.equals(nodeAspectsThree));
assertTrue("Expected cm:titled aspect", nodeAspectsFour.contains(ContentModel.ASPECT_TITLED));
// Remove an aspect
nodeService.removeAspect(nodeRef, ContentModel.ASPECT_TITLED);
// Get the values for the previous version
Map<QName, Serializable> nodePropsFourCheck = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeyFour);
Set<QName> nodeAspectsFourCheck = (Set<QName>) findCacheValue(aspectsCache, nodeKeyFour);
assertTrue("Previous cache entries must be left alone", nodePropsFourCheck.equals(nodePropsFour));
assertTrue("Previous cache entries must be left alone", nodeAspectsFourCheck.equals(nodeAspectsFour));
// Get the current node cache key
Node nodeFive = (Node) findCacheValue(nodesCache, nodeId);
assertNotNull("Node not found in cache", nodeFive);
NodeVersionKey nodeKeyFive = nodeFive.getNodeVersionKey();
// Get the node cached values
Map<QName, Serializable> nodePropsFive = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeyFive);
Set<QName> nodeAspectsFive = (Set<QName>) findCacheValue(aspectsCache, nodeKeyFive);
// Check the values
assertEquals("The node version is incorrect", Long.valueOf(5L), nodeKeyFive.getVersion());
assertNotNull("No cache entry for properties", nodePropsFive);
assertNotNull("No cache entry for aspects", nodeAspectsFive);
assertTrue("Properties must be carried", nodePropsFive.equals(nodePropsFour));
assertFalse("Aspects must have moved on", nodeAspectsFive.equals(nodeAspectsFour));
assertFalse("Expected no cm:titled aspect ", nodeAspectsFive.contains(ContentModel.ASPECT_TITLED));
// Add an aspect, some properties and secondary association
RetryingTransactionCallback<Void> nodeSixWork = new RetryingTransactionCallback<Void>() {
@Override
public Void execute() throws Throwable {
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
props.put(ContentModel.PROP_TITLE, "some title");
nodeService.addAspect(nodeRef, ContentModel.ASPECT_TITLED, props);
nodeService.setProperty(nodeRef, ContentModel.PROP_DESCRIPTION, "Some description");
// QName.createQName(TEST_PREFIX, "secondary"));
return null;
}
};
txnService.getRetryingTransactionHelper().doInTransaction(nodeSixWork);
// Get the values for the previous version
Map<QName, Serializable> nodePropsFiveCheck = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeyFive);
Set<QName> nodeAspectsFiveCheck = (Set<QName>) findCacheValue(aspectsCache, nodeKeyFive);
assertTrue("Previous cache entries must be left alone", nodePropsFiveCheck.equals(nodePropsFive));
assertTrue("Previous cache entries must be left alone", nodeAspectsFiveCheck.equals(nodeAspectsFive));
// Get the current node cache key
Node nodeSix = (Node) findCacheValue(nodesCache, nodeId);
assertNotNull("Node not found in cache", nodeSix);
NodeVersionKey nodeKeySix = nodeSix.getNodeVersionKey();
// Get the node cached values
Map<QName, Serializable> nodePropsSix = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeySix);
Set<QName> nodeAspectsSix = (Set<QName>) findCacheValue(aspectsCache, nodeKeySix);
// Check the values
assertEquals("The node version is incorrect", Long.valueOf(6L), nodeKeySix.getVersion());
assertNotNull("No cache entry for properties", nodePropsSix);
assertNotNull("No cache entry for aspects", nodeAspectsSix);
assertFalse("Properties must have moved on", nodePropsSix.equals(nodePropsFive));
assertEquals("Property count incorrect", 3, nodePropsSix.size());
assertNotNull("Expected a cm:name property", nodePropsSix.get(ContentModel.PROP_NAME));
assertNotNull("Expected a cm:title property", nodePropsSix.get(ContentModel.PROP_TITLE));
assertNotNull("Expected a cm:description property", nodePropsSix.get(ContentModel.PROP_DESCRIPTION));
assertFalse("Aspects must have moved on", nodeAspectsSix.equals(nodeAspectsFive));
assertTrue("Expected cm:titled aspect ", nodeAspectsSix.contains(ContentModel.ASPECT_TITLED));
// Remove an aspect, some properties and a secondary association
RetryingTransactionCallback<Void> nodeSevenWork = new RetryingTransactionCallback<Void>() {
@Override
public Void execute() throws Throwable {
nodeService.removeAspect(nodeRef, ContentModel.ASPECT_TITLED);
nodeService.removeChild(workspaceRootNodeRef, nodeRef);
return null;
}
};
txnService.getRetryingTransactionHelper().doInTransaction(nodeSevenWork);
// Get the values for the previous version
Map<QName, Serializable> nodePropsSixCheck = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeySix);
Set<QName> nodeAspectsSixCheck = (Set<QName>) findCacheValue(aspectsCache, nodeKeySix);
assertTrue("Previous cache entries must be left alone", nodePropsSixCheck.equals(nodePropsSix));
assertTrue("Previous cache entries must be left alone", nodeAspectsSixCheck.equals(nodeAspectsSix));
// Get the current node cache key
Node nodeSeven = (Node) findCacheValue(nodesCache, nodeId);
assertNotNull("Node not found in cache", nodeSeven);
NodeVersionKey nodeKeySeven = nodeSeven.getNodeVersionKey();
// Get the node cached values
Map<QName, Serializable> nodePropsSeven = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeySeven);
Set<QName> nodeAspectsSeven = (Set<QName>) findCacheValue(aspectsCache, nodeKeySeven);
// Check the values
assertEquals("The node version is incorrect", Long.valueOf(7L), nodeKeySeven.getVersion());
assertNotNull("No cache entry for properties", nodePropsSeven);
assertNotNull("No cache entry for aspects", nodeAspectsSeven);
assertFalse("Properties must have moved on", nodePropsSeven.equals(nodePropsSix));
assertEquals("Property count incorrect", 1, nodePropsSeven.size());
assertNotNull("Expected a cm:name property", nodePropsSeven.get(ContentModel.PROP_NAME));
assertFalse("Aspects must have moved on", nodeAspectsSeven.equals(nodeAspectsSix));
assertFalse("Expected no cm:titled aspect ", nodeAspectsSeven.contains(ContentModel.ASPECT_TITLED));
// Modify cm:auditable
RetryingTransactionCallback<Void> nodeEightWork = new RetryingTransactionCallback<Void>() {
@Override
public Void execute() throws Throwable {
BehaviourFilter behaviourFilter = (BehaviourFilter) APP_CONTEXT_INIT.getApplicationContext().getBean("policyBehaviourFilter");
// Disable behaviour for txn
behaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
nodeService.setProperty(nodeRef, ContentModel.PROP_MODIFIER, "Fred");
return null;
}
};
txnService.getRetryingTransactionHelper().doInTransaction(nodeEightWork);
// Get the values for the previous version
Map<QName, Serializable> nodePropsSevenCheck = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeySeven);
Set<QName> nodeAspectsSevenCheck = (Set<QName>) findCacheValue(aspectsCache, nodeKeySeven);
assertTrue("Previous cache entries must be left alone", nodePropsSevenCheck.equals(nodePropsSeven));
assertTrue("Previous cache entries must be left alone", nodeAspectsSevenCheck.equals(nodeAspectsSeven));
// Get the current node cache key
Node nodeEight = (Node) findCacheValue(nodesCache, nodeId);
assertNotNull("Node not found in cache", nodeEight);
NodeVersionKey nodeKeyEight = nodeEight.getNodeVersionKey();
// Get the node cached values
Map<QName, Serializable> nodePropsEight = (Map<QName, Serializable>) findCacheValue(propsCache, nodeKeyEight);
Set<QName> nodeAspectsEight = (Set<QName>) findCacheValue(aspectsCache, nodeKeyEight);
// Check the values
assertEquals("The node version is incorrect", Long.valueOf(8L), nodeKeyEight.getVersion());
assertNotNull("No cache entry for properties", nodePropsEight);
assertNotNull("No cache entry for aspects", nodeAspectsEight);
assertEquals("Expected change to cm:modifier", "Fred", nodeEight.getAuditableProperties().getAuditModifier());
assertTrue("Properties must be carried", nodePropsEight.equals(nodePropsSeven));
assertTrue("Aspects be carried", nodeAspectsEight.equals(nodeAspectsSeven));
}
Aggregations