mirror of
https://github.com/Alfresco/SearchServices.git
synced 2026-09-16 18:12:56 +00:00
Merge branch 'master' of github.com:Alfresco/SearchServices into fix/SEARCH-1490_cascading_not_work_in_sharding_environment
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
# 3. Combined Codebase
|
||||
|
||||
Date: 09/04/2019
|
||||
|
||||
## Status
|
||||
|
||||
Approved
|
||||
|
||||
## Context
|
||||
|
||||
Historically Alfresco has had a bad experience of having a monolithic codebase in SVN. The main issue with this was the
|
||||
inability to easily work on feature branches, resulting in frequent conflicting changes. To make matters worse this was
|
||||
seen as hard to move to git, since GitHub has/had a maximum limit on repository size and there were several large
|
||||
binary artifacts stored in the Alfresco history [[1]].
|
||||
|
||||
More recently the Alfresco codebase has been split into a large number of small git repositories [[2]].
|
||||
|
||||
This proposal is to merge the various git repositories together. By doing this we aim to:
|
||||
|
||||
1. Remove the effort of creating releases of library projects.
|
||||
1. Allow tests to be written on the same branch (in the same repository) as the production code (i.e. facilitate TDD).
|
||||
1. Make it easier for everyone (especially people outside the team and new starters) to find the 'right bit' of code.
|
||||
|
||||
[1]: https://community.alfresco.com/community/ecm/blog/2015/04/01/so-when-is-alfresco-moving-to-github
|
||||
|
||||
[2]: https://ts.alfresco.com/share/proxy/alfresco/api/node/content/versionStore/version2Store/a0c2492f-6354-4b98-adfc-e63d5c2209f5/SearchCodeBase.png
|
||||
|
||||
## Decision
|
||||
|
||||
We will merge the search-related repositories together and preserve their history. We will not attempt to merge code
|
||||
that other teams also need (for example the TAS test utilities or the alfresco-data-model projects).
|
||||
|
||||
## Consequences
|
||||
|
||||
An epic has been raised containing the next steps [[3]]. Broadly speaking these are:
|
||||
|
||||
1. Merge the alfresco-solr-client library with the SearchServices repository.
|
||||
1. Merge the insight-engine, insight-jdbc and insight-zeppelin repositories.
|
||||
1. A consequence of this is that future releases of these artifacts will share version numbers.
|
||||
1. Put all the end-to-end tests in a single testing project.
|
||||
1. Merge the (public) SearchServices code into the (private) InsightEngine repository and set up a mirror so the
|
||||
community code is still publicly editable.
|
||||
1. Merge the tests with the production code.
|
||||
1. Merge the build scripts with the production code.
|
||||
|
||||
[3]: https://issues.alfresco.com/jira/browse/SEARCH-1393
|
||||
@@ -0,0 +1,44 @@
|
||||
# 4. Community Mirror
|
||||
|
||||
Date: 09/04/2019
|
||||
|
||||
## Status
|
||||
|
||||
Approved
|
||||
|
||||
## Context
|
||||
|
||||
In [ADR 3: "Combined Codebase"](0003-combined-codebase.md) we decided to merge the Search Services and Insight Engine
|
||||
repositories. Since we want to enable the community to submit pull requests to the Search Services project we need a
|
||||
way to keep this code up to date on GitHub.
|
||||
|
||||
## Decision
|
||||
|
||||
We will mirror `master` and all branches starting with `release/` to a branch with the same name on GitHub. We will
|
||||
exclude the alfresco-insight-engine-parent directory. We will include these commands as part of our build to do this:
|
||||
|
||||
```
|
||||
# This avoids making changes to the original branch.
|
||||
get checkout -b tempBranch
|
||||
# This strips all enterprise changes (in a reproducible way) and pushes any updates to the mirror.
|
||||
git filter-branch -f --prune-empty --index-filter 'git rm -r --cached --ignore-unmatch alfresco-insight-engine-parent'
|
||||
git push out HEAD:$branch
|
||||
# This resets us back to where we were before the filtering.
|
||||
git checkout $branch
|
||||
```
|
||||
|
||||
## Consequences
|
||||
|
||||
A ticket has been raised to track this [[1]]. A script has been written to do the initial codebase merge and
|
||||
mirroring [[2]].
|
||||
|
||||
We will rewrite the whole history of the SearchServices repository using the mirroring command. This will result in the
|
||||
new repository containing a new root pom file and the search services code beneath that.
|
||||
|
||||
All changes except those within the module called insight-engine will be mirrored.
|
||||
|
||||
The root pom file in the community project will include a reference to the insight-engine pom file, so community users
|
||||
will have to build from within the alfresco-search-parent directory.
|
||||
|
||||
[1]: https://issues.alfresco.com/jira/browse/SEARCH-1397
|
||||
[2]: https://git.alfresco.com/search_discovery/combinerScript/blob/master/combineSearch.sh
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
# 5. Merge Tests And Production Code
|
||||
|
||||
Date: 09/04/2019
|
||||
|
||||
## Status
|
||||
|
||||
Approved
|
||||
|
||||
## Context
|
||||
|
||||
In [ADR 3: "Combined Codebase"](0003-combined-codebase.md) we decided to merge the production and end-to-end test
|
||||
repositories. In [ADR 4: "Community Mirror"](0004-community-mirror.md) we discuss setting up a mirror for the community
|
||||
code.
|
||||
|
||||
## Decision
|
||||
|
||||
We will separate the end-to-end test code in half so that any code solely related to Insight Engine won't be mirrored.
|
||||
|
||||
We will remove the existing test groups for the different versions of Search Services and Insight Engine, and instead
|
||||
delete any tests from branches where they should not be run.
|
||||
|
||||
## Consequences
|
||||
|
||||
It will be possible to include production code changes along with all required test changes in the same merge request.
|
||||
It will be easy to get new tests running before production code is written without causing other branches to fail.
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
# 6. Release Synchronisation
|
||||
|
||||
Date: 24/04/2019
|
||||
|
||||
## Status
|
||||
|
||||
Approved
|
||||
|
||||
## Context
|
||||
|
||||
In [ADR 3: "Combined Codebase"](0003-combined-codebase.md) we decided to merge the Search Services and Insight Engine
|
||||
repositories. In [ADR 4: "Community Mirror"](0004-community-mirror.md) we discussed how we would set up a build job to
|
||||
ensure community code is available to the community. In particular we decided:
|
||||
|
||||
> We will mirror `master` and all branches starting with `release/` to a branch with the same name on GitHub.
|
||||
|
||||
## Decision
|
||||
|
||||
During the combining of the Search Services and Insight Engine codebases we will create a branch `master` by merging
|
||||
the existing `master` branches of those two projects. We will update the version of Insight Engine to match Search Services - that
|
||||
is 1.4.0-SNAPSHOT.
|
||||
|
||||
## Consequences
|
||||
|
||||
The next minor release of Insight Engine will be 1.4.0 which will happen at the same time as the release of Search
|
||||
Services 1.4.0. There will be no Insight Engine releases with the versions 1.2.x or 1.3.x.
|
||||
|
||||
Here are a few examples to illustrate the process for future releases. Note that other releases (including service
|
||||
packs, etc.) will follow a similar logic based on whether they are pre- or post- 1.4.0.
|
||||
|
||||
* SS 1.3.0 needs a hotfix
|
||||
|
||||
We release from the `release/alfresco-search-services/V1.3.0.x` branch.
|
||||
|
||||
* IE 1.1.0 needs a hotfix
|
||||
|
||||
We release from the `release/alfresco-insight-engine/V1.1.0.x` branch. We need to use the maven version 1.1.0.2 for the
|
||||
IE modules and 1.4.0-IE1.1.0.2 for the SS modules.
|
||||
|
||||
* SS 1.4.0 needs a hotfix
|
||||
|
||||
We'll create a hotfix release for both SS and IE (since they will both have the same issue). This will be from the
|
||||
`release/V1.4.0.x` branch (which would have already been created if SS/IE 1.4.0 had been released).
|
||||
|
||||
* IE 1.4.0 needs a hotfix
|
||||
|
||||
We'll create a hotfix release for both SS and IE from `release/V1.4.0.x` (and not publicise SS 1.4.0.1).
|
||||
+5
@@ -145,6 +145,7 @@ import org.apache.lucene.util.BytesRefBuilder;
|
||||
import org.apache.solr.common.SolrDocument;
|
||||
import org.apache.solr.common.SolrDocumentList;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
import org.apache.solr.common.SolrInputField;
|
||||
import org.apache.solr.common.params.CommonParams;
|
||||
import org.apache.solr.common.params.FacetParams;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
@@ -2354,6 +2355,10 @@ public class SolrInformationServer implements InformationServer
|
||||
|
||||
if (cachedDoc != null)
|
||||
{
|
||||
ofNullable(cachedDoc.getField("MINHASH"))
|
||||
.map(SolrInputField::getValue)
|
||||
.ifPresent(minHash -> newDoc.setField("MINHASH", minHash));
|
||||
|
||||
// Builds up the new solr doc from the cached content regardless of whether or not it is current
|
||||
List<FieldInstance> fields = AlfrescoSolrDataModel.getInstance().getIndexedFieldNamesForProperty(
|
||||
propertyQName).getFields();
|
||||
|
||||
+268
-222
@@ -19,50 +19,75 @@
|
||||
|
||||
package org.alfresco.solr.query;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.solr.AbstractAlfrescoSolrTests;
|
||||
import org.alfresco.solr.client.*;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
import org.alfresco.solr.client.AclChangeSet;
|
||||
import org.alfresco.solr.client.AclReaders;
|
||||
import org.alfresco.solr.client.Node;
|
||||
import org.alfresco.solr.client.NodeMetaData;
|
||||
import org.alfresco.solr.client.SOLRAPIQueueClient;
|
||||
import org.alfresco.solr.client.StringPropertyValue;
|
||||
import org.alfresco.solr.client.Transaction;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.LegacyNumericRangeQuery;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Arrays.stream;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.stream.IntStream.range;
|
||||
import static org.alfresco.solr.AlfrescoSolrUtils.*;
|
||||
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class AlfrescoSolrFingerprintTest extends AbstractAlfrescoSolrTests
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(AlfrescoSolrFingerprintTest.class);
|
||||
private static long MAX_WAIT_TIME = 80000;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception
|
||||
{
|
||||
initAlfrescoCore("schema-fingerprint.xml");
|
||||
initAlfrescoCore("schema.xml");
|
||||
}
|
||||
|
||||
private Acl acl;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
// if you override setUp or tearDown, you better callf
|
||||
// the super classes version
|
||||
//clearIndex();
|
||||
//assertU(commit());
|
||||
public void prepare() throws Exception
|
||||
{
|
||||
AclChangeSet aclChangeSet = getAclChangeSet(1);
|
||||
acl = getAcl(aclChangeSet);
|
||||
Acl acl2 = getAcl(aclChangeSet);
|
||||
|
||||
AclReaders aclReaders = getAclReaders(aclChangeSet, acl, singletonList("joel"), singletonList("phil"), null);
|
||||
AclReaders aclReaders2 = getAclReaders(aclChangeSet, acl2, singletonList("jim"), singletonList("phil"), null);
|
||||
|
||||
indexAclChangeSet(aclChangeSet,
|
||||
asList(acl, acl2),
|
||||
asList(aclReaders, aclReaders2));
|
||||
|
||||
// Check for the ACL state stamp.
|
||||
BooleanQuery.Builder builder = new BooleanQuery.Builder();
|
||||
builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_SOLR4_ID, "TRACKER!STATE!ACLTX")), BooleanClause.Occur.MUST));
|
||||
builder.add(new BooleanClause(LegacyNumericRangeQuery.newLongRange(QueryConstants.FIELD_S_ACLTXID, aclChangeSet.getId(), aclChangeSet.getId() + 1, true, false), BooleanClause.Occur.MUST));
|
||||
BooleanQuery waitForQuery = builder.build();
|
||||
waitForDocCount(waitForQuery, 1, MAX_WAIT_TIME);
|
||||
}
|
||||
|
||||
@After
|
||||
public void clearQueue() throws Exception {
|
||||
public void clearQueue()
|
||||
{
|
||||
SOLRAPIQueueClient.nodeMetaDataMap.clear();
|
||||
SOLRAPIQueueClient.transactionQueue.clear();
|
||||
SOLRAPIQueueClient.aclChangeSetQueue.clear();
|
||||
@@ -70,234 +95,255 @@ public class AlfrescoSolrFingerprintTest extends AbstractAlfrescoSolrTests
|
||||
SOLRAPIQueueClient.aclMap.clear();
|
||||
SOLRAPIQueueClient.nodeMap.clear();
|
||||
SOLRAPIQueueClient.nodeContentMap.clear();
|
||||
|
||||
clearIndex();
|
||||
assertU(commit());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBasciFingerPrint() throws Exception
|
||||
private void makeSureTransactionHasBeenIndexed(long transactionId) throws Exception
|
||||
{
|
||||
/*
|
||||
* Create and index an AclChangeSet.
|
||||
*/
|
||||
|
||||
logger.info("######### Starting fingerprint test ###########");
|
||||
AclChangeSet aclChangeSet = getAclChangeSet(1);
|
||||
|
||||
Acl acl = getAcl(aclChangeSet);
|
||||
Acl acl2 = getAcl(aclChangeSet);
|
||||
|
||||
|
||||
AclReaders aclReaders = getAclReaders(aclChangeSet, acl, list("joel"), list("phil"), null);
|
||||
AclReaders aclReaders2 = getAclReaders(aclChangeSet, acl2, list("jim"), list("phil"), null);
|
||||
|
||||
|
||||
indexAclChangeSet(aclChangeSet,
|
||||
list(acl, acl2),
|
||||
list(aclReaders, aclReaders2));
|
||||
|
||||
|
||||
//Check for the ACL state stamp.
|
||||
//Check for the TXN state stamp.
|
||||
BooleanQuery.Builder builder = new BooleanQuery.Builder();
|
||||
builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_SOLR4_ID, "TRACKER!STATE!ACLTX")), BooleanClause.Occur.MUST));
|
||||
builder.add(new BooleanClause(LegacyNumericRangeQuery.newLongRange(QueryConstants.FIELD_S_ACLTXID, aclChangeSet.getId(), aclChangeSet.getId() + 1, true, false), BooleanClause.Occur.MUST));
|
||||
builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_SOLR4_ID, "TRACKER!STATE!TX")), BooleanClause.Occur.MUST));
|
||||
builder.add(new BooleanClause(LegacyNumericRangeQuery.newLongRange(QueryConstants.FIELD_S_TXID, transactionId, transactionId + 1, true, false), BooleanClause.Occur.MUST));
|
||||
BooleanQuery waitForQuery = builder.build();
|
||||
waitForDocCount(waitForQuery, 1, MAX_WAIT_TIME);
|
||||
}
|
||||
|
||||
logger.info("#################### Passed First Test ##############################");
|
||||
|
||||
/*
|
||||
* Create and index a Transaction
|
||||
*/
|
||||
|
||||
//First create a transaction.
|
||||
@Test
|
||||
public void testBasicFingerprint() throws Exception
|
||||
{
|
||||
Transaction txn = getTransaction(0, 4);
|
||||
|
||||
//Next create two nodes to update for the transaction
|
||||
Node node1 = getNode(txn, acl, Node.SolrApiNodeStatus.UPDATED);
|
||||
Node node2 = getNode(txn, acl, Node.SolrApiNodeStatus.UPDATED);
|
||||
Node node3 = getNode(txn, acl, Node.SolrApiNodeStatus.UPDATED);
|
||||
Node node4 = getNode(txn, acl, Node.SolrApiNodeStatus.UPDATED);
|
||||
|
||||
|
||||
//Next create the NodeMetaData for each node. TODO: Add more metadata
|
||||
NodeMetaData nodeMetaData1 = getNodeMetaData(node1, txn, acl, "mike", null, false);
|
||||
NodeMetaData nodeMetaData2 = getNodeMetaData(node2, txn, acl, "mike", null, false);
|
||||
NodeMetaData nodeMetaData3 = getNodeMetaData(node3, txn, acl, "mike", null, false);
|
||||
NodeMetaData nodeMetaData4 = getNodeMetaData(node4, txn, acl, "mike", null, false);
|
||||
|
||||
List<String> content = new ArrayList();
|
||||
Random randomizer = new Random(1);
|
||||
String aFirstToken = Integer.toString(Math.abs(randomizer.nextInt()));
|
||||
|
||||
indexTransaction(txn,
|
||||
asList(node1, node2, node3, node4),
|
||||
asList(nodeMetaData1, nodeMetaData2, nodeMetaData3, nodeMetaData4),
|
||||
randomTextContent());
|
||||
|
||||
makeSureTransactionHasBeenIndexed(txn.getId());
|
||||
makeSureContentNodesHaveBeenIndexed("mike", aFirstToken, 4);
|
||||
|
||||
assertFingerprintQueryCorrectness(node1.getId(),
|
||||
"*[count(//doc)= 4]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node2.getId()+"']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='"+node3.getId()+"']",
|
||||
"//result/doc[4]/long[@name='DBID'][.='"+node4.getId()+"']");
|
||||
|
||||
assertFingerprintQueryCorrectness(nodeMetaData1.getNodeRef().getId(),
|
||||
"*[count(//doc)= 4]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node2.getId()+"']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='"+node3.getId()+"']",
|
||||
"//result/doc[4]/long[@name='DBID'][.='"+node4.getId()+"']");
|
||||
|
||||
assertFingerprintQueryCorrectness(node1.getId() + "_70",
|
||||
"*[count(//doc)= 2]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node3.getId()+"']");
|
||||
|
||||
assertFingerprintQueryCorrectness(nodeMetaData1.getNodeRef().getId() + "_70",
|
||||
"*[count(//doc)= 2]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node3.getId()+"']");
|
||||
|
||||
assertFingerprintQueryCorrectness(node1.getId() + "_45",
|
||||
"*[count(//doc)= 3]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node2.getId()+"']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='"+node3.getId()+"']");
|
||||
|
||||
assertFingerprintQueryCorrectness(nodeMetaData1.getNodeRef().getId() + "_45",
|
||||
"*[count(//doc)= 3]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node2.getId()+"']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='"+node3.getId()+"']");
|
||||
|
||||
assertFingerprintQueryCorrectness(node4.getId() + "_30",
|
||||
"*[count(//doc)= 4]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node2.getId()+"']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='"+node3.getId()+"']",
|
||||
"//result/doc[4]/long[@name='DBID'][.='"+node4.getId()+"']");
|
||||
|
||||
assertFingerprintQueryCorrectness(nodeMetaData4.getNodeRef().getId() + "_30",
|
||||
"*[count(//doc)= 4]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node2.getId()+"']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='"+node3.getId()+"']",
|
||||
"//result/doc[4]/long[@name='DBID'][.='"+node4.getId()+"']");
|
||||
|
||||
assertFingerprintQueryCorrectness(node4.getId(),
|
||||
"*[count(//doc)= 4]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node2.getId()+"']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='"+node3.getId()+"']",
|
||||
"//result/doc[4]/long[@name='DBID'][.='"+node4.getId()+"']");
|
||||
|
||||
assertFingerprintQueryCorrectness(nodeMetaData4.getNodeRef().getId(),
|
||||
"*[count(//doc)= 4]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node2.getId()+"']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='"+node3.getId()+"']",
|
||||
"//result/doc[4]/long[@name='DBID'][.='"+node4.getId()+"']");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFingerprintStillExistsAfterNodeMetadataUpdate() throws Exception
|
||||
{
|
||||
Transaction txn = getTransaction(0, 1);
|
||||
Node fileNode = getNode(txn, acl, Node.SolrApiNodeStatus.UPDATED);
|
||||
NodeMetaData fileMetaData = getNodeMetaData(fileNode, txn, acl, "mike", null, false);
|
||||
|
||||
indexTransaction(
|
||||
txn,
|
||||
singletonList(fileNode),
|
||||
singletonList(fileMetaData),
|
||||
singletonList("This is a text content which is longer than the default hello world " + fileNode.getId() +
|
||||
" returned by the Mock SOLRAPIQueueClient. This is needed because the \"min_hash\" field type " +
|
||||
"definition in Solr doesn't take in account fields which produce less than 5 tokens (see the " +
|
||||
"ShingleFilter settings)."));
|
||||
|
||||
makeSureTransactionHasBeenIndexed(txn.getId());
|
||||
makeSureContentNodeHasBeenIndexed(fileNode, "mike", "world");
|
||||
|
||||
assertFingerprintQueryCorrectness(fileNode.getId(), "*[count(//doc)=1]","//result/doc[1]/long[@name='DBID'][.='" + fileNode.getId() + "']");
|
||||
|
||||
// Let's update the test node
|
||||
fileMetaData.setOwner("Andrea");
|
||||
fileMetaData.getProperties().put(ContentModel.PROP_TITLE, new StringPropertyValue("This is the new file \"title\" metadata attribute."));
|
||||
reindexTransactionId(txn.getId());
|
||||
|
||||
makeSureContentNodeHasBeenIndexed(fileNode, "Andrea", "world");
|
||||
|
||||
assertFingerprintQueryCorrectness(fileNode.getId(), "*[count(//doc)=1]","//result/doc[1]/long[@name='DBID'][.='" + fileNode.getId() + "']");
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the index using a token from the (dummy) text produced by the test framework ("world", actually).
|
||||
* Once the query returns a positive result we are sure the ContentTracker
|
||||
*
|
||||
* <ol>
|
||||
* <li>
|
||||
* Fetched the text content associated with the current node, from Alfresco
|
||||
* </li>
|
||||
* <li>
|
||||
* Computed a fingerprint (using the retrieved text) for the node
|
||||
* </li>
|
||||
* <li>
|
||||
* Updated the node definition in the (Solr)ContentStore and in Solr
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* Last but not least, we are also making sure that CommitTracker executed its cycle as well (otherwise document
|
||||
* wouldn't be searchable).
|
||||
*
|
||||
* @param node an addition term which will be appended as a required clause in the executed query.
|
||||
* @param testTerm a term which is supposed to be in the indexed content
|
||||
* @param owner the #FIELD_OWNER which will be used as an additional required query clause.
|
||||
* @throws Exception in case the MAX_WAIT_TIME is reached and the node is not in results.
|
||||
*/
|
||||
private void makeSureContentNodeHasBeenIndexed(final Node node, final String owner, String testTerm) throws Exception
|
||||
{
|
||||
waitForDocCount(new TermQuery(new Term(QueryConstants.FIELD_READER, "jim")), 1, MAX_WAIT_TIME);
|
||||
waitForDocCount(new TermQuery(new Term("content@s___t@{http://www.alfresco.org/model/content/1.0}content", testTerm)), 1, MAX_WAIT_TIME);
|
||||
|
||||
waitForDocCount(new TermQuery(new Term("content@s___t@{http://www.alfresco.org/model/content/1.0}content", Long.toString(node.getId()))), 1, MAX_WAIT_TIME);
|
||||
|
||||
BooleanQuery.Builder builder = new BooleanQuery.Builder();
|
||||
builder.add(new BooleanClause(new TermQuery(new Term("content@s___t@{http://www.alfresco.org/model/content/1.0}content", testTerm)), BooleanClause.Occur.MUST));
|
||||
builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_OWNER, owner)), BooleanClause.Occur.MUST));
|
||||
waitForDocCount(builder.build(), 1, MAX_WAIT_TIME);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Queries the index using a token from the (dummy) text produced by the test framework.
|
||||
* Once the query returns a positive result we are sure the ContentTracker
|
||||
*
|
||||
* <ol>
|
||||
* <li>
|
||||
* Fetched the text content associated with the test nodes, from Alfresco
|
||||
* </li>
|
||||
* <li>
|
||||
* Computed a fingerprint (using the retrieved text) for each node
|
||||
* </li>
|
||||
* <li>
|
||||
* Updated the nodes definitions in the (Solr)ContentStore and in Solr
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* Last but not least, we are also making sure that CommitTracker executed its cycle as well (otherwise documents
|
||||
* wouldn't be searchable).
|
||||
*
|
||||
* @param owner the #FIELD_OWNER which will be used as an additional required query clause.
|
||||
* @param testTerm a term which is supposed to be in the indexed content
|
||||
* @throws Exception in case the MAX_WAIT_TIME is reached and the node is not in results.
|
||||
*/
|
||||
private void makeSureContentNodesHaveBeenIndexed(final String owner, String testTerm, final int expectedCount) throws Exception
|
||||
{
|
||||
waitForDocCount(new TermQuery(new Term(QueryConstants.FIELD_READER, "jim")), 1, MAX_WAIT_TIME);
|
||||
waitForDocCount(new TermQuery(new Term("content@s___t@{http://www.alfresco.org/model/content/1.0}content", testTerm)), expectedCount, MAX_WAIT_TIME);
|
||||
|
||||
BooleanQuery.Builder builder = new BooleanQuery.Builder();
|
||||
builder.add(new BooleanClause(new TermQuery(new Term("content@s___t@{http://www.alfresco.org/model/content/1.0}content", testTerm)), BooleanClause.Occur.MUST));
|
||||
builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_OWNER, owner)), BooleanClause.Occur.MUST));
|
||||
waitForDocCount(builder.build(), expectedCount, MAX_WAIT_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a query in the format <pre>FINGERPRINT:<DBID></pre> correctly returns the node we are testing.
|
||||
*
|
||||
* @param id the node identifier.
|
||||
*/
|
||||
private void assertFingerprintQueryCorrectness(long id, String ... assertions)
|
||||
{
|
||||
assertFingerprintQueryCorrectness(String.valueOf(id), assertions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a query in the format <pre>FINGERPRINT:<DBID></pre> correctly returns the node we are testing.
|
||||
*
|
||||
* @param id the node identifier.
|
||||
*/
|
||||
private void assertFingerprintQueryCorrectness(String id, String ... assertions)
|
||||
{
|
||||
ModifiableSolrParams params = new ModifiableSolrParams()
|
||||
.add("q", "FINGERPRINT:" + id)
|
||||
.add("qt", "/afts")
|
||||
.add("start", "0")
|
||||
.add("rows", "6")
|
||||
.add("sort", "id asc");
|
||||
// .add("fq", "{!afts}AUTHORITY_FILTER_FROM_JSON");
|
||||
|
||||
SolrServletRequest req = areq(params, "{\"locales\":[\"en\"], \"templates\": [{\"name\":\"t1\", \"template\":\"%cm:content\"}], \"authorities\": [ \"joel\"], \"tenants\": [ \"\" ]}");
|
||||
assertQ(req, assertions);
|
||||
}
|
||||
|
||||
private List<String> randomTextContent()
|
||||
{
|
||||
int[] sizes = {2000, 1000, 1500, 750};
|
||||
|
||||
Random r = new Random(1);
|
||||
String token1 = Integer.toString(Math.abs(r.nextInt()));
|
||||
|
||||
for(int i=0; i<4; i++) {
|
||||
Random rand = new Random(1);
|
||||
StringBuilder buf = new StringBuilder();
|
||||
int size = sizes[i];
|
||||
for(int s=0; s<size; s++) {
|
||||
if(s>0) {
|
||||
buf.append(" ");
|
||||
}
|
||||
buf.append(Integer.toString(Math.abs(rand.nextInt())));
|
||||
}
|
||||
content.add(buf.toString());
|
||||
}
|
||||
|
||||
//Index the transaction, nodes, and nodeMetaDatas.
|
||||
//Note that the content is automatically created by the test framework.
|
||||
indexTransaction(txn,
|
||||
list(node1, node2, node3, node4),
|
||||
list(nodeMetaData1, nodeMetaData2, nodeMetaData3, nodeMetaData4),
|
||||
content);
|
||||
|
||||
//Check for the TXN state stamp.
|
||||
logger.info("#################### Started Second Test ##############################");
|
||||
builder = new BooleanQuery.Builder();
|
||||
builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_SOLR4_ID, "TRACKER!STATE!TX")), BooleanClause.Occur.MUST));
|
||||
builder.add(new BooleanClause(LegacyNumericRangeQuery.newLongRange(QueryConstants.FIELD_S_TXID, txn.getId(), txn.getId() + 1, true, false), BooleanClause.Occur.MUST));
|
||||
waitForQuery = builder.build();
|
||||
|
||||
waitForDocCount(waitForQuery, 1, MAX_WAIT_TIME);
|
||||
logger.info("#################### Passed Second Test ##############################");
|
||||
|
||||
/*
|
||||
* Query the index for the content
|
||||
*/
|
||||
|
||||
waitForDocCount(new TermQuery(new Term(QueryConstants.FIELD_READER, "jim")), 1, MAX_WAIT_TIME);
|
||||
waitForDocCount(new TermQuery(new Term("content@s___t@{http://www.alfresco.org/model/content/1.0}content", token1)), 4, MAX_WAIT_TIME);
|
||||
|
||||
logger.info("#################### Passed Third Test ##############################");
|
||||
|
||||
ModifiableSolrParams params = new ModifiableSolrParams();
|
||||
params.add("q", "FINGERPRINT:" + node1.getId()); //Query for an id in the content field. The node id is automatically populated into the content field by test framework
|
||||
params.add("qt", "/afts");
|
||||
params.add("fl", "DBID,score");
|
||||
params.add("start", "0");
|
||||
params.add("rows", "6");
|
||||
SolrServletRequest req = areq(params, null);
|
||||
assertQ(req, "*[count(//doc)=4]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='" + node1.getId() + "']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='" + node3.getId() + "']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='" + node2.getId() + "']",
|
||||
"//result/doc[4]/long[@name='DBID'][.='" + node4.getId() + "']");
|
||||
|
||||
params = new ModifiableSolrParams();
|
||||
params.add("q", "FINGERPRINT:" + node1.getId() + "_70"); //Query for an id in the content field. The node id is automatically populated into the content field by test framework
|
||||
params.add("qt", "/afts");
|
||||
params.add("fl","DBID,score");
|
||||
params.add("start", "0");
|
||||
params.add("rows", "6");
|
||||
req = areq(params, null);
|
||||
assertQ(req, "*[count(//doc)= 2]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node3.getId()+"']");
|
||||
|
||||
params = new ModifiableSolrParams();
|
||||
params.add("q", "FINGERPRINT:" + node1.getId()+"_45"); //Query for an id in the content field. The node id is automatically populated into the content field by test framework
|
||||
params.add("qt", "/afts");
|
||||
params.add("fl","DBID,score");
|
||||
params.add("start", "0");
|
||||
params.add("rows", "6");
|
||||
req = areq(params, null);
|
||||
assertQ(req, "*[count(//doc)= 3]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node3.getId()+"']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='"+node2.getId()+"']");
|
||||
|
||||
params = new ModifiableSolrParams();
|
||||
params.add("q", "FINGERPRINT:" + node1.getId()+"_30");
|
||||
params.add("qt", "/afts");
|
||||
params.add("fl","DBID,score");
|
||||
params.add("start", "0");
|
||||
params.add("rows", "6");
|
||||
req = areq(params, null);
|
||||
assertQ(req, "*[count(//doc)= 4]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node3.getId()+"']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='"+node2.getId()+"']",
|
||||
"//result/doc[4]/long[@name='DBID'][.='"+node4.getId()+"']");
|
||||
|
||||
|
||||
params = new ModifiableSolrParams();
|
||||
params.add("q", "FINGERPRINT:" + node4.getId());
|
||||
params.add("qt", "/afts");
|
||||
params.add("fl","DBID,score");
|
||||
params.add("start", "0");
|
||||
params.add("rows", "6");
|
||||
req = areq(params, null);
|
||||
assertQ(req, "*[count(//doc)= 4]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node4.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node2.getId()+"']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='"+node3.getId()+"']",
|
||||
"//result/doc[4]/long[@name='DBID'][.='"+node1.getId()+"']");
|
||||
|
||||
//Test nodeRef
|
||||
|
||||
params = new ModifiableSolrParams();
|
||||
params.add("q", "FINGERPRINT:" + nodeMetaData1.getNodeRef().getId()); //Query for an id in the content field. The node id is automatically populated into the content field by test framework
|
||||
params.add("qt", "/afts");
|
||||
params.add("fl", "DBID,score");
|
||||
params.add("start", "0");
|
||||
params.add("rows", "6");
|
||||
|
||||
req = areq(params, null);
|
||||
assertQ(req, "*[count(//doc)=4]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='" + node1.getId() + "']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='" + node3.getId() + "']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='" + node2.getId() + "']",
|
||||
"//result/doc[4]/long[@name='DBID'][.='" + node4.getId() + "']");
|
||||
|
||||
params = new ModifiableSolrParams();
|
||||
params.add("q", "FINGERPRINT:" + nodeMetaData1.getNodeRef().getId() + "_70"); //Query for an id in the content field. The node id is automatically populated into the content field by test framework
|
||||
params.add("qt", "/afts");
|
||||
params.add("fl","DBID,score");
|
||||
params.add("start", "0");
|
||||
params.add("rows", "6");
|
||||
req = areq(params, null);
|
||||
assertQ(req, "*[count(//doc)= 2]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node3.getId()+"']");
|
||||
|
||||
params = new ModifiableSolrParams();
|
||||
params.add("q", "FINGERPRINT:" + nodeMetaData1.getNodeRef().getId()+"_45"); //Query for an id in the content field. The node id is automatically populated into the content field by test framework
|
||||
params.add("qt", "/afts");
|
||||
params.add("fl","DBID,score");
|
||||
params.add("start", "0");
|
||||
params.add("rows", "6");
|
||||
req = areq(params, null);
|
||||
assertQ(req, "*[count(//doc)= 3]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node3.getId()+"']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='"+node2.getId()+"']");
|
||||
|
||||
params = new ModifiableSolrParams();
|
||||
params.add("q", "FINGERPRINT:" + nodeMetaData1.getNodeRef().getId()+"_30");
|
||||
params.add("qt", "/afts");
|
||||
params.add("fl","DBID,score");
|
||||
params.add("start", "0");
|
||||
params.add("rows", "6");
|
||||
req = areq(params, null);
|
||||
assertQ(req, "*[count(//doc)= 4]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node3.getId()+"']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='"+node2.getId()+"']",
|
||||
"//result/doc[4]/long[@name='DBID'][.='"+node4.getId()+"']");
|
||||
|
||||
|
||||
params = new ModifiableSolrParams();
|
||||
params.add("q", "FINGERPRINT:" + nodeMetaData4.getNodeRef().getId());
|
||||
params.add("qt", "/afts");
|
||||
params.add("fl","DBID,score");
|
||||
params.add("start", "0");
|
||||
params.add("rows", "6");
|
||||
req = areq(params, null);
|
||||
assertQ(req, "*[count(//doc)= 4]",
|
||||
"//result/doc[1]/long[@name='DBID'][.='"+node4.getId()+"']",
|
||||
"//result/doc[2]/long[@name='DBID'][.='"+node2.getId()+"']",
|
||||
"//result/doc[3]/long[@name='DBID'][.='"+node3.getId()+"']",
|
||||
"//result/doc[4]/long[@name='DBID'][.='"+node1.getId()+"']");
|
||||
|
||||
return stream(sizes)
|
||||
.mapToObj(item -> {
|
||||
Random randomizer = new Random(1);
|
||||
return range(0, item)
|
||||
.mapToObj(i -> randomizer.nextInt())
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.joining(" "));})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
+156
-70
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.alfresco.solr.query;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.alfresco.solr.AlfrescoSolrUtils.getAcl;
|
||||
import static org.alfresco.solr.AlfrescoSolrUtils.getAclChangeSet;
|
||||
import static org.alfresco.solr.AlfrescoSolrUtils.getAclReaders;
|
||||
@@ -25,12 +26,13 @@ import static org.alfresco.solr.AlfrescoSolrUtils.getNode;
|
||||
import static org.alfresco.solr.AlfrescoSolrUtils.getNodeMetaData;
|
||||
import static org.alfresco.solr.AlfrescoSolrUtils.getTransaction;
|
||||
import static org.alfresco.solr.AlfrescoSolrUtils.indexAclChangeSet;
|
||||
import static org.alfresco.solr.AlfrescoSolrUtils.list;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
|
||||
import org.alfresco.solr.AbstractAlfrescoDistributedTest;
|
||||
import org.alfresco.solr.client.Acl;
|
||||
@@ -38,6 +40,7 @@ import org.alfresco.solr.client.AclChangeSet;
|
||||
import org.alfresco.solr.client.AclReaders;
|
||||
import org.alfresco.solr.client.Node;
|
||||
import org.alfresco.solr.client.NodeMetaData;
|
||||
import org.alfresco.solr.client.StringPropertyValue;
|
||||
import org.alfresco.solr.client.Transaction;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
@@ -60,31 +63,26 @@ import org.junit.Test;
|
||||
@LuceneTestCase.SuppressCodecs({"Appending","Lucene3x","Lucene40","Lucene41","Lucene42","Lucene43", "Lucene44", "Lucene45","Lucene46","Lucene47","Lucene48","Lucene49"})
|
||||
public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDistributedTest
|
||||
{
|
||||
private static Node[] nodes = new Node[4];
|
||||
private static NodeMetaData[] nodesMetada = new NodeMetaData[4];
|
||||
|
||||
private static long MAX_WAIT_TIME = 80000;
|
||||
|
||||
private static Node[] NODES = new Node[4];
|
||||
private static NodeMetaData[] NODES_METADATA = new NodeMetaData[4];
|
||||
private static Acl ACL;
|
||||
|
||||
@BeforeClass
|
||||
private static void initData() throws Throwable
|
||||
{
|
||||
initSolrServers(2,"DistributedAlfrescoSolrFingerPrintTest",null);
|
||||
/*
|
||||
* Create and index an AclChangeSet.
|
||||
*/
|
||||
initSolrServers(2,getClassName(),null);
|
||||
|
||||
AclChangeSet aclChangeSet = getAclChangeSet(1);
|
||||
|
||||
Acl acl = getAcl(aclChangeSet);
|
||||
ACL = getAcl(aclChangeSet);
|
||||
Acl acl2 = getAcl(aclChangeSet);
|
||||
|
||||
AclReaders aclReaders = getAclReaders(aclChangeSet, ACL, singletonList("joel"), singletonList("phil"), null);
|
||||
AclReaders aclReaders2 = getAclReaders(aclChangeSet, acl2, singletonList("jim"), singletonList("phil"), null);
|
||||
|
||||
AclReaders aclReaders = getAclReaders(aclChangeSet, acl, list("joel"), list("phil"), null);
|
||||
AclReaders aclReaders2 = getAclReaders(aclChangeSet, acl2, list("jim"), list("phil"), null);
|
||||
|
||||
|
||||
indexAclChangeSet(aclChangeSet,
|
||||
list(acl, acl2),
|
||||
list(aclReaders, aclReaders2));
|
||||
|
||||
indexAclChangeSet(aclChangeSet, asList(ACL, acl2), asList(aclReaders, aclReaders2));
|
||||
|
||||
//Check for the ACL state stamp.
|
||||
BooleanQuery.Builder builder = new BooleanQuery.Builder();
|
||||
@@ -93,27 +91,22 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
BooleanQuery waitForQuery = builder.build();
|
||||
waitForDocCountAllCores(waitForQuery, 1, 80000);
|
||||
|
||||
/*
|
||||
* Create and index a Transaction
|
||||
*/
|
||||
|
||||
//First create a transaction.
|
||||
Transaction txn = getTransaction(0, 4);
|
||||
|
||||
//Next create two nodes to update for the transaction
|
||||
nodes[0] = getNode(txn, acl, Node.SolrApiNodeStatus.UPDATED);
|
||||
nodes[1] = getNode(txn, acl, Node.SolrApiNodeStatus.UPDATED);
|
||||
nodes[2] = getNode(txn, acl, Node.SolrApiNodeStatus.UPDATED);
|
||||
nodes[3] = getNode(txn, acl, Node.SolrApiNodeStatus.UPDATED);
|
||||
//Next create two NODES to update for the transaction
|
||||
NODES[0] = getNode(txn, ACL, Node.SolrApiNodeStatus.UPDATED);
|
||||
NODES[1] = getNode(txn, ACL, Node.SolrApiNodeStatus.UPDATED);
|
||||
NODES[2] = getNode(txn, ACL, Node.SolrApiNodeStatus.UPDATED);
|
||||
NODES[3] = getNode(txn, ACL, Node.SolrApiNodeStatus.UPDATED);
|
||||
|
||||
|
||||
//Next create the NodeMetaData for each node. TODO: Add more metadata
|
||||
nodesMetada[0] = getNodeMetaData(nodes[0], txn, acl, "mike", null, false);
|
||||
nodesMetada[1] = getNodeMetaData(nodes[1], txn, acl, "mike", null, false);
|
||||
nodesMetada[2] = getNodeMetaData(nodes[2], txn, acl, "mike", null, false);
|
||||
nodesMetada[3] = getNodeMetaData(nodes[3], txn, acl, "mike", null, false);
|
||||
NODES_METADATA[0] = getNodeMetaData(NODES[0], txn, ACL, "mike", null, false);
|
||||
NODES_METADATA[1] = getNodeMetaData(NODES[1], txn, ACL, "mike", null, false);
|
||||
NODES_METADATA[2] = getNodeMetaData(NODES[2], txn, ACL, "mike", null, false);
|
||||
NODES_METADATA[3] = getNodeMetaData(NODES[3], txn, ACL, "mike", null, false);
|
||||
|
||||
List<String> content = new ArrayList();
|
||||
List<String> content = new ArrayList<>();
|
||||
int[] sizes = {2000, 1000, 1500, 750};
|
||||
|
||||
Random r = new Random(1);
|
||||
@@ -127,16 +120,16 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
if(s>0) {
|
||||
buf.append(" ");
|
||||
}
|
||||
buf.append(Integer.toString(Math.abs(rand.nextInt())));
|
||||
buf.append(Math.abs(rand.nextInt()));
|
||||
}
|
||||
content.add(buf.toString());
|
||||
}
|
||||
|
||||
//Index the transaction, nodes, and nodeMetaDatas.
|
||||
//Index the transaction, NODES, and nodeMetaDatas.
|
||||
//Note that the content is automatically created by the test framework.
|
||||
indexTransaction(txn,
|
||||
list(nodes[0], nodes[1], nodes[2], nodes[3]),
|
||||
list(nodesMetada[0], nodesMetada[1], nodesMetada[2], nodesMetada[3]),
|
||||
asList(NODES[0], NODES[1], NODES[2], NODES[3]),
|
||||
asList(NODES_METADATA[0], NODES_METADATA[1], NODES_METADATA[2], NODES_METADATA[3]),
|
||||
content);
|
||||
|
||||
//Check for the TXN state stamp.
|
||||
@@ -156,7 +149,7 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
private static void destroyData() throws Throwable
|
||||
private static void destroyData()
|
||||
{
|
||||
dismissSolrServers();
|
||||
}
|
||||
@@ -167,7 +160,7 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
putHandleDefaults();
|
||||
QueryResponse response = query(getDefaultTestClient(), true,
|
||||
"{\"locales\":[\"en\"], \"templates\": [{\"name\":\"t1\", \"template\":\"%cm:content\"}], \"authorities\": [\"joel\"], \"tenants\": []}",
|
||||
params("q", "FINGERPRINT:"+nodes[0].getId(),
|
||||
params("q", "FINGERPRINT:"+ NODES[0].getId(),
|
||||
"qt", "/afts",
|
||||
"shards.qt", "/afts",
|
||||
"start", "0",
|
||||
@@ -175,22 +168,22 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
"rows", "100"));
|
||||
|
||||
SolrDocumentList docs = response.getResults();
|
||||
assertTrue(docs.getNumFound() == 4);
|
||||
assertEquals(4, docs.getNumFound());
|
||||
SolrDocument doc0 = docs.get(0);
|
||||
long dbid0 = (long)doc0.getFieldValue("DBID");
|
||||
assertTrue(dbid0 == nodes[0].getId());
|
||||
assertEquals(dbid0, NODES[0].getId());
|
||||
|
||||
SolrDocument doc1 = docs.get(1);
|
||||
long dbid1 = (long)doc1.getFieldValue("DBID");
|
||||
assertTrue(dbid1 == nodes[2].getId());
|
||||
assertEquals(dbid1, NODES[2].getId());
|
||||
|
||||
SolrDocument doc2 = docs.get(2);
|
||||
long dbid2 = (long)doc2.getFieldValue("DBID");
|
||||
assertTrue(dbid2 == nodes[1].getId());
|
||||
assertEquals(dbid2, NODES[1].getId());
|
||||
|
||||
SolrDocument doc3 = docs.get(3);
|
||||
long dbid3 = (long)doc3.getFieldValue("DBID");
|
||||
assertTrue(dbid3 == nodes[3].getId());
|
||||
assertEquals(dbid3, NODES[3].getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -199,7 +192,7 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
putHandleDefaults();
|
||||
QueryResponse response = query(getDefaultTestClient(), true,
|
||||
"{\"locales\":[\"en\"], \"templates\": [{\"name\":\"t1\", \"template\":\"%cm:content\"}], \"authorities\": [\"joel\"], \"tenants\": []}",
|
||||
params("q", "FINGERPRINT:" + nodes[0].getId()+"_70",
|
||||
params("q", "FINGERPRINT:" + NODES[0].getId()+"_70",
|
||||
"qt", "/afts",
|
||||
"shards.qt", "/afts",
|
||||
"start", "0",
|
||||
@@ -207,14 +200,14 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
"rows", "100"));
|
||||
|
||||
SolrDocumentList docs = response.getResults();
|
||||
assertTrue(docs.getNumFound() == 2);
|
||||
assertEquals(2, docs.getNumFound());
|
||||
SolrDocument doc0 = docs.get(0);
|
||||
long dbid0 = (long)doc0.getFieldValue("DBID");
|
||||
assertTrue(dbid0 == nodes[0].getId());
|
||||
assertEquals(dbid0, NODES[0].getId());
|
||||
|
||||
SolrDocument doc1 = docs.get(1);
|
||||
long dbid1 = (long)doc1.getFieldValue("DBID");
|
||||
assertTrue(dbid1 == nodes[2].getId());
|
||||
assertEquals(dbid1, NODES[2].getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -223,7 +216,7 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
putHandleDefaults();
|
||||
QueryResponse response = query(getDefaultTestClient(), true,
|
||||
"{\"locales\":[\"en\"], \"templates\": [{\"name\":\"t1\", \"template\":\"%cm:content\"}], \"authorities\": [\"joel\"], \"tenants\": []}",
|
||||
params("q", "FINGERPRINT:" + nodes[0].getId()+"_45",
|
||||
params("q", "FINGERPRINT:" + NODES[0].getId()+"_45",
|
||||
"qt", "/afts",
|
||||
"shards.qt", "/afts",
|
||||
"start", "0",
|
||||
@@ -231,18 +224,18 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
"rows", "100"));
|
||||
|
||||
SolrDocumentList docs = response.getResults();
|
||||
assertTrue(docs.getNumFound() == 3);
|
||||
assertEquals(3, docs.getNumFound());
|
||||
SolrDocument doc0 = docs.get(0);
|
||||
long dbid0 = (long)doc0.getFieldValue("DBID");
|
||||
assertTrue(dbid0 == nodes[0].getId());
|
||||
assertEquals(dbid0, NODES[0].getId());
|
||||
|
||||
SolrDocument doc1 = docs.get(1);
|
||||
long dbid1 = (long)doc1.getFieldValue("DBID");
|
||||
assertTrue(dbid1 == nodes[2].getId());
|
||||
assertEquals(dbid1, NODES[2].getId());
|
||||
|
||||
SolrDocument doc2 = docs.get(2);
|
||||
long dbid2 = (long)doc2.getFieldValue("DBID");
|
||||
assertTrue(dbid2 == nodes[1].getId());
|
||||
assertEquals(dbid2, NODES[1].getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -251,7 +244,7 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
putHandleDefaults();
|
||||
QueryResponse response = query(getDefaultTestClient(), true,
|
||||
"{\"locales\":[\"en\"], \"templates\": [{\"name\":\"t1\", \"template\":\"%cm:content\"}], \"authorities\": [\"joel\"], \"tenants\": []}",
|
||||
params("q", "FINGERPRINT:"+nodesMetada[0].getNodeRef().getId(),
|
||||
params("q", "FINGERPRINT:"+ NODES_METADATA[0].getNodeRef().getId(),
|
||||
"qt", "/afts",
|
||||
"shards.qt", "/afts",
|
||||
"start", "0",
|
||||
@@ -259,22 +252,22 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
"rows", "100"));
|
||||
|
||||
SolrDocumentList docs = response.getResults();
|
||||
assertTrue(docs.getNumFound() == 4);
|
||||
assertEquals(4, docs.getNumFound());
|
||||
SolrDocument doc0 = docs.get(0);
|
||||
long dbid0 = (long)doc0.getFieldValue("DBID");
|
||||
assertTrue(dbid0 == nodes[0].getId());
|
||||
assertEquals(dbid0, NODES[0].getId());
|
||||
|
||||
SolrDocument doc1 = docs.get(1);
|
||||
long dbid1 = (long)doc1.getFieldValue("DBID");
|
||||
assertTrue(dbid1 == nodes[2].getId());
|
||||
assertEquals(dbid1, NODES[2].getId());
|
||||
|
||||
SolrDocument doc2 = docs.get(2);
|
||||
long dbid2 = (long)doc2.getFieldValue("DBID");
|
||||
assertTrue(dbid2 == nodes[1].getId());
|
||||
assertEquals(dbid2, NODES[1].getId());
|
||||
|
||||
SolrDocument doc3 = docs.get(3);
|
||||
long dbid3 = (long)doc3.getFieldValue("DBID");
|
||||
assertTrue(dbid3 == nodes[3].getId());
|
||||
assertEquals(dbid3, NODES[3].getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -283,7 +276,7 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
putHandleDefaults();
|
||||
QueryResponse response = query(getDefaultTestClient(), true,
|
||||
"{\"locales\":[\"en\"], \"templates\": [{\"name\":\"t1\", \"template\":\"%cm:content\"}], \"authorities\": [\"joel\"], \"tenants\": []}",
|
||||
params("q", "FINGERPRINT:" + nodesMetada[0].getNodeRef().getId() +"_70",
|
||||
params("q", "FINGERPRINT:" + NODES_METADATA[0].getNodeRef().getId() +"_70",
|
||||
"qt", "/afts",
|
||||
"shards.qt", "/afts",
|
||||
"start", "0",
|
||||
@@ -291,14 +284,14 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
"rows", "100"));
|
||||
|
||||
SolrDocumentList docs = response.getResults();
|
||||
assertTrue(docs.getNumFound() == 2);
|
||||
assertEquals(2, docs.getNumFound());
|
||||
SolrDocument doc0 = docs.get(0);
|
||||
long dbid0 = (long)doc0.getFieldValue("DBID");
|
||||
assertTrue(dbid0 == nodes[0].getId());
|
||||
assertEquals(dbid0, NODES[0].getId());
|
||||
|
||||
SolrDocument doc1 = docs.get(1);
|
||||
long dbid1 = (long)doc1.getFieldValue("DBID");
|
||||
assertTrue(dbid1 == nodes[2].getId());
|
||||
assertEquals(dbid1, NODES[2].getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -307,7 +300,7 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
putHandleDefaults();
|
||||
QueryResponse response = query(getDefaultTestClient(), true,
|
||||
"{\"locales\":[\"en\"], \"templates\": [{\"name\":\"t1\", \"template\":\"%cm:content\"}], \"authorities\": [\"joel\"], \"tenants\": []}",
|
||||
params("q", "FINGERPRINT:" + nodesMetada[0].getNodeRef().getId() +"_45",
|
||||
params("q", "FINGERPRINT:" + NODES_METADATA[0].getNodeRef().getId() +"_45",
|
||||
"qt", "/afts",
|
||||
"shards.qt", "/afts",
|
||||
"start", "0",
|
||||
@@ -315,20 +308,113 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
|
||||
"rows", "100"));
|
||||
|
||||
SolrDocumentList docs = response.getResults();
|
||||
assertTrue(docs.getNumFound() == 3);
|
||||
assertEquals(3, docs.getNumFound());
|
||||
SolrDocument doc0 = docs.get(0);
|
||||
long dbid0 = (long)doc0.getFieldValue("DBID");
|
||||
assertTrue(dbid0 == nodes[0].getId());
|
||||
assertEquals(dbid0, NODES[0].getId());
|
||||
|
||||
SolrDocument doc1 = docs.get(1);
|
||||
long dbid1 = (long)doc1.getFieldValue("DBID");
|
||||
assertTrue(dbid1 == nodes[2].getId());
|
||||
assertEquals(dbid1, NODES[2].getId());
|
||||
|
||||
SolrDocument doc2 = docs.get(2);
|
||||
long dbid2 = (long)doc2.getFieldValue("DBID");
|
||||
assertTrue(dbid2 == nodes[1].getId());
|
||||
assertEquals(dbid2, NODES[1].getId());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFingerprintStillExistsAfterNodeMetadataUpdate() throws Exception
|
||||
{
|
||||
putHandleDefaults();
|
||||
|
||||
Transaction txn = getTransaction(0, 1);
|
||||
Node fileNode = getNode(txn, ACL, Node.SolrApiNodeStatus.UPDATED);
|
||||
NodeMetaData fileMetaData = getNodeMetaData(fileNode, txn, ACL, "mike", null, false);
|
||||
|
||||
indexTransaction(
|
||||
txn,
|
||||
singletonList(fileNode),
|
||||
singletonList(fileMetaData),
|
||||
singletonList("This is a text content which is longer than the default hello world " + fileNode.getId() +
|
||||
" returned by the Mock SOLRAPIQueueClient. This is needed because the \"min_hash\" field type " +
|
||||
"definition in Solr doesn't take in account fields which produce less than 5 tokens (see the " +
|
||||
"ShingleFilter settings)."));
|
||||
|
||||
makeSureContentNodeHasBeenIndexed(fileNode, "mike", "longer");
|
||||
|
||||
QueryResponse response = query(getDefaultTestClient(), true,
|
||||
"{\"locales\":[\"en\"], \"templates\": [{\"name\":\"t1\", \"template\":\"%cm:content\"}], \"authorities\": [\"joel\"], \"tenants\": []}",
|
||||
params("q", "FINGERPRINT:" + fileMetaData.getNodeRef().getId(),
|
||||
"qt", "/afts",
|
||||
"shards.qt", "/afts",
|
||||
"start", "0",
|
||||
"fl", "DBID,score",
|
||||
"rows", "100"));
|
||||
|
||||
SolrDocumentList docs = response.getResults();
|
||||
assertEquals(1, docs.getNumFound());
|
||||
assertEquals(fileNode.getId(), docs.iterator().next().getFieldValue("DBID"));
|
||||
|
||||
// Let's update the test node
|
||||
fileMetaData.setOwner("Andrea");
|
||||
fileMetaData.getProperties().put(ContentModel.PROP_TITLE, new StringPropertyValue("This is the new file \"title\" metadata attribute."));
|
||||
|
||||
txn = getTransaction(0, 1);
|
||||
|
||||
indexTransaction(
|
||||
txn,
|
||||
singletonList(fileNode),
|
||||
singletonList(fileMetaData));
|
||||
|
||||
makeSureContentNodeHasBeenIndexed(fileNode, "Andrea", "longer");
|
||||
|
||||
response = query(getDefaultTestClient(), true,
|
||||
"{\"locales\":[\"en\"], \"templates\": [{\"name\":\"t1\", \"template\":\"%cm:content\"}], \"authorities\": [\"joel\"], \"tenants\": []}",
|
||||
params("q", "FINGERPRINT:" + fileMetaData.getNodeRef().getId(),
|
||||
"qt", "/afts",
|
||||
"shards.qt", "/afts",
|
||||
"start", "0",
|
||||
"fl", "DBID,score",
|
||||
"rows", "100"));
|
||||
docs = response.getResults();
|
||||
assertEquals(1, docs.getNumFound());
|
||||
assertEquals(fileNode.getId(), docs.iterator().next().getFieldValue("DBID"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the index using a token from the (dummy) text produced by the test framework ("world", actually).
|
||||
* Once the query returns a positive result we are sure the ContentTracker
|
||||
*
|
||||
* <ol>
|
||||
* <li>
|
||||
* Fetched the text content associated with the current node, from Alfresco
|
||||
* </li>
|
||||
* <li>
|
||||
* Computed a fingerprint (using the retrieved text) for the node
|
||||
* </li>
|
||||
* <li>
|
||||
* Updated the node definition in the (Solr)ContentStore and in Solr
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* Last but not least, we are also making sure that CommitTracker executed its cycle as well (otherwise document
|
||||
* wouldn't be searchable).
|
||||
*
|
||||
* @param node an addition term which will be appended as a required clause in the executed query.
|
||||
* @param testTerm a term which is supposed to be in the indexed content
|
||||
* @param owner the #FIELD_OWNER which will be used as an additional required query clause.
|
||||
* @throws Exception in case the MAX_WAIT_TIME is reached and the node is not in results.
|
||||
*/
|
||||
private void makeSureContentNodeHasBeenIndexed(final Node node, final String owner, String testTerm) throws Exception
|
||||
{
|
||||
waitForDocCount(new TermQuery(new Term(QueryConstants.FIELD_READER, "jim")), 1, MAX_WAIT_TIME);
|
||||
waitForDocCount(new TermQuery(new Term("content@s___t@{http://www.alfresco.org/model/content/1.0}content", testTerm)), 1, MAX_WAIT_TIME);
|
||||
|
||||
waitForDocCount(new TermQuery(new Term("content@s___t@{http://www.alfresco.org/model/content/1.0}content", Long.toString(node.getId()))), 1, MAX_WAIT_TIME);
|
||||
|
||||
BooleanQuery.Builder builder = new BooleanQuery.Builder();
|
||||
builder.add(new BooleanClause(new TermQuery(new Term("content@s___t@{http://www.alfresco.org/model/content/1.0}content", testTerm)), BooleanClause.Occur.MUST));
|
||||
builder.add(new BooleanClause(new TermQuery(new Term(QueryConstants.FIELD_OWNER, owner)), BooleanClause.Occur.MUST));
|
||||
waitForDocCount(builder.build(), 1, MAX_WAIT_TIME);
|
||||
}
|
||||
}
|
||||
-769
@@ -1,769 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!--
|
||||
TODO
|
||||
- Geospatial ?
|
||||
- Currency ?
|
||||
- (default facetting configuration)
|
||||
-->
|
||||
<schema name="Alfresco V2.0" version="1.5">
|
||||
<types>
|
||||
<!-- ID and version to support SOLR cloud -->
|
||||
|
||||
<fieldType name="identifier" class="solr.StrField" sortMissingLast="true" positionIncrementGap="100" />
|
||||
<fieldType name="version" class="solr.TrieLongField" precisionStep="64" positionIncrementGap="0" />
|
||||
|
||||
|
||||
<fieldType name="lowercase_id" class="solr.TextField" sortMissingLast="true" omitNorms="true" positionIncrementGap="100" >
|
||||
<analyzer>
|
||||
<tokenizer class="solr.KeywordTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory" />
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Fixed analysis for numeric types - query, range, facet, and sorting-->
|
||||
|
||||
<fieldType name="int" class="solr.TrieIntField" precisionStep="4" positionIncrementGap="100" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<fieldType name="float" class="solr.TrieFloatField" precisionStep="4" positionIncrementGap="100" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<fieldType name="long" class="solr.TrieLongField" precisionStep="6" positionIncrementGap="100" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<fieldType name="double" class="solr.TrieDoubleField" precisionStep="6" positionIncrementGap="100" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<fieldType name="date" class="solr.TrieDateField" precisionStep="6" positionIncrementGap="100" sortMissingLast="false" sortMissingFirst="false" />
|
||||
|
||||
<!-- Fixed stats analysis for numeric types - stats -->
|
||||
|
||||
<fieldType name="stats_int" class="solr.TrieIntField" precisionStep="32" positionIncrementGap="100" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<fieldType name="stats_float" class="solr.TrieFloatField" precisionStep="64" positionIncrementGap="100" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<fieldType name="stats_long" class="solr.TrieLongField" precisionStep="32" positionIncrementGap="100" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<fieldType name="stats_double" class="solr.TrieDoubleField" precisionStep="64" positionIncrementGap="100" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<fieldType name="stats_date" class="solr.TrieDateField" precisionStep="64" positionIncrementGap="100" sortMissingLast="false" sortMissingFirst="false" />
|
||||
|
||||
<!-- All text fields are handled via the Alfresco data model -->
|
||||
<!-- All anlysis is defined in dummy field types which this field type uses -->
|
||||
|
||||
<!-- TODO: truncated text field for sorting?? -->
|
||||
|
||||
<fieldType name="oldStandardAnalysis" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.ASCIIFoldingFilterFactory"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
|
||||
<fieldType name="alfrescoFieldType" class="org.alfresco.solr.AlfrescoFieldType" />
|
||||
|
||||
<fieldType name="alfrescoCollatableMLTextFieldType" class="org.alfresco.solr.AlfrescoCollatableMLTextFieldType" sortMissingLast="true" />
|
||||
|
||||
<fieldType name="path" class="solr.TextField" >
|
||||
<analyzer class="org.alfresco.repo.search.impl.lucene.analysis.PathAnalyzer" />
|
||||
</fieldType>
|
||||
|
||||
<fieldType name="location_rpt" class="solr.SpatialRecursivePrefixTreeFieldType"
|
||||
spatialContextFactory="org.locationtech.spatial4j.context.SpatialContextFactory"
|
||||
distErrPct="0.025"
|
||||
maxDistErr="0.000009"
|
||||
distanceUnits="degrees" />
|
||||
|
||||
|
||||
<!-- Suggestion -->
|
||||
|
||||
<fieldType name="text_shingle" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer type="index">
|
||||
<tokenizer class="solr.ICUTokenizerFactory"/>
|
||||
<filter class="solr.ICUNormalizer2FilterFactory" name="nfkc_cf" mode="compose" />
|
||||
<filter class="solr.ShingleFilterFactory" minShingleSize="2" maxShingleSize="3" outputUnigrams="true" outputUnigramsIfNoShingles="true" tokenSeparator=" " />
|
||||
</analyzer>
|
||||
<analyzer type="query">
|
||||
<tokenizer class="solr.ICUTokenizerFactory"/>
|
||||
<filter class="solr.ICUNormalizer2FilterFactory" name="nfkc_cf" mode="compose" />
|
||||
<filter class="solr.ShingleFilterFactory" minShingleSize="2" maxShingleSize="3" outputUnigrams="false" outputUnigramsIfNoShingles="true" tokenSeparator=" " />
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<fieldType name="text_min_hash" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer type="index">
|
||||
<tokenizer class="solr.ICUTokenizerFactory"/>
|
||||
<filter class="solr.ICUNormalizer2FilterFactory" name="nfkc_cf" mode="compose" />
|
||||
<filter class="solr.ShingleFilterFactory" minShingleSize="5" maxShingleSize="5" outputUnigrams="false" outputUnigramsIfNoShingles="false" tokenSeparator=" " />
|
||||
<!--
|
||||
<filter class="org.apache.lucene.analysis.minhash.ContextAccumulatingFilterFactory" />
|
||||
-->
|
||||
<filter class="org.apache.lucene.analysis.minhash.MinHashFilterFactory" hashCount="1" hashSetSize="1" bucketCount="512" />
|
||||
</analyzer>
|
||||
<analyzer type="query">
|
||||
<tokenizer class="solr.KeywordTokenizerFactory" />
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<fieldType name="text_plain" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.ICUTokenizerFactory"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Cross-locale -->
|
||||
<!-- Include word splitting -->
|
||||
|
||||
<fieldType name="text___" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.ICUTokenizerFactory"/>
|
||||
<!-- <tokenizer class="org.apache.solr.analysis.WhitespaceTokenizerFactory" /> -->
|
||||
<filter class="org.apache.solr.analysis.WordDelimiterFilterFactory"
|
||||
generateWordParts="1"
|
||||
generateNumberParts="1"
|
||||
catenateWords="1"
|
||||
catenateNumbers="1"
|
||||
catenateAll="1"
|
||||
splitOnCaseChange="1"
|
||||
splitOnNumerics="1"
|
||||
preserveOriginal="1"
|
||||
stemEnglishPossessive="1"/>
|
||||
<filter class="solr.ICUFoldingFilterFactory"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
|
||||
<fieldType name="alfrescoCollatableTextFieldType" class="org.alfresco.solr.AlfrescoCollatableTextFieldType" sortMissingLast="true" />
|
||||
|
||||
<!-- -->
|
||||
<!-- Field types that are only used to define language specific analysis (generally ordered by ISO code) -->
|
||||
<!-- -->
|
||||
|
||||
<!-- English -->
|
||||
<fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer type="index">
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<!-- in this example, we will only use synonyms at query time
|
||||
<filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
|
||||
-->
|
||||
<filter class="solr.ICUFoldingFilterFactory"/>
|
||||
<filter class="solr.EnglishPossessiveFilterFactory"/>
|
||||
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
|
||||
<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
|
||||
<filter class="solr.EnglishMinimalStemFilterFactory"/>
|
||||
-->
|
||||
<filter class="solr.PorterStemFilterFactory"/>
|
||||
<filter class="solr.CommonGramsFilterFactory" words="lang/stopwords_en.txt" ignoreCase="true"/>
|
||||
</analyzer>
|
||||
<analyzer type="query">
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
|
||||
<filter class="solr.ICUFoldingFilterFactory"/>
|
||||
<filter class="solr.EnglishPossessiveFilterFactory"/>
|
||||
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
|
||||
<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
|
||||
<filter class="solr.EnglishMinimalStemFilterFactory"/>
|
||||
-->
|
||||
<filter class="solr.PorterStemFilterFactory"/>
|
||||
<filter class="solr.CommonGramsQueryFilterFactory" words="lang/stopwords_en.txt" ignoreCase="true"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Arabic -->
|
||||
<fieldType name="text_ar" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<!-- for any non-arabic -->
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ar.txt" />
|
||||
<!-- normalizes ~ to ~, etc -->
|
||||
<filter class="solr.ArabicNormalizationFilterFactory"/>
|
||||
<filter class="solr.ArabicStemFilterFactory"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Bulgarian -->
|
||||
<fieldType name="text_bg" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_bg.txt" />
|
||||
<filter class="solr.BulgarianStemFilterFactory"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Catalan -->
|
||||
<fieldType name="text_ca" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<!-- removes l', etc -->
|
||||
<filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_ca.txt"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ca.txt" />
|
||||
<filter class="solr.SnowballPorterFilterFactory" language="Catalan"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- CJK bigram (see text_ja for a Japanese configuration using morphological analysis) -->
|
||||
<fieldType name="text_cjk" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<!-- normalize width before bigram, as e.g. half-width dakuten combine -->
|
||||
<filter class="solr.CJKWidthFilterFactory"/>
|
||||
<!-- for any non-CJK -->
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.CJKBigramFilterFactory"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Kurdish -->
|
||||
<fieldType name="text_ckb" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.SoraniNormalizationFilterFactory"/>
|
||||
<!-- for any latin text -->
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ckb.txt"/>
|
||||
<filter class="solr.SoraniStemFilterFactory"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Czech -->
|
||||
<fieldType name="text_cz" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_cz.txt" />
|
||||
<filter class="solr.CzechStemFilterFactory"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Danish -->
|
||||
<fieldType name="text_da" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_da.txt" format="snowball" />
|
||||
<filter class="solr.SnowballPorterFilterFactory" language="Danish"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- German -->
|
||||
<fieldType name="text_de" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_de.txt" format="snowball" />
|
||||
<filter class="solr.GermanNormalizationFilterFactory"/>
|
||||
<filter class="solr.GermanLightStemFilterFactory"/>
|
||||
<!-- less aggressive: <filter class="solr.GermanMinimalStemFilterFactory"/> -->
|
||||
<!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="German2"/> -->
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Greek -->
|
||||
<fieldType name="text_el" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<!-- greek specific lowercase for sigma -->
|
||||
<filter class="solr.GreekLowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="false" words="lang/stopwords_el.txt" />
|
||||
<filter class="solr.GreekStemFilterFactory"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Spanish -->
|
||||
<fieldType name="text_es" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_es.txt" format="snowball" />
|
||||
<filter class="solr.SpanishLightStemFilterFactory"/>
|
||||
<!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="Spanish"/> -->
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Basque -->
|
||||
<fieldType name="text_eu" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_eu.txt" />
|
||||
<filter class="solr.SnowballPorterFilterFactory" language="Basque"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Persian -->
|
||||
<fieldType name="text_fa" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<!-- for ZWNJ -->
|
||||
<charFilter class="solr.PersianCharFilterFactory"/>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.ArabicNormalizationFilterFactory"/>
|
||||
<filter class="solr.PersianNormalizationFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_fa.txt" />
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Finnish -->
|
||||
<fieldType name="text_fi" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_fi.txt" format="snowball" />
|
||||
<filter class="solr.SnowballPorterFilterFactory" language="Finnish"/>
|
||||
<!-- less aggressive: <filter class="solr.FinnishLightStemFilterFactory"/> -->
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- French -->
|
||||
<fieldType name="text_fr" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<!-- removes l', etc -->
|
||||
<filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_fr.txt"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_fr.txt" format="snowball" />
|
||||
<filter class="solr.FrenchLightStemFilterFactory"/>
|
||||
<!-- less aggressive: <filter class="solr.FrenchMinimalStemFilterFactory"/> -->
|
||||
<!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="French"/> -->
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Irish -->
|
||||
<fieldType name="text_ga" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<!-- removes d', etc -->
|
||||
<filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_ga.txt"/>
|
||||
<!-- removes n-, etc. position increments is intentionally false! -->
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/hyphenations_ga.txt"/>
|
||||
<filter class="solr.IrishLowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ga.txt"/>
|
||||
<filter class="solr.SnowballPorterFilterFactory" language="Irish"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Galician -->
|
||||
<fieldType name="text_gl" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_gl.txt" />
|
||||
<filter class="solr.GalicianStemFilterFactory"/>
|
||||
<!-- less aggressive: <filter class="solr.GalicianMinimalStemFilterFactory"/> -->
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Hindi -->
|
||||
<fieldType name="text_hi" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<!-- normalizes unicode representation -->
|
||||
<filter class="solr.IndicNormalizationFilterFactory"/>
|
||||
<!-- normalizes variation in spelling -->
|
||||
<filter class="solr.HindiNormalizationFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_hi.txt" />
|
||||
<filter class="solr.HindiStemFilterFactory"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Hungarian -->
|
||||
<fieldType name="text_hu" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_hu.txt" format="snowball" />
|
||||
<filter class="solr.SnowballPorterFilterFactory" language="Hungarian"/>
|
||||
<!-- less aggressive: <filter class="solr.HungarianLightStemFilterFactory"/> -->
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Armenian -->
|
||||
<fieldType name="text_hy" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_hy.txt" />
|
||||
<filter class="solr.SnowballPorterFilterFactory" language="Armenian"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Indonesian -->
|
||||
<fieldType name="text_id" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_id.txt" />
|
||||
<!-- for a less aggressive approach (only inflectional suffixes), set stemDerivational to false -->
|
||||
<filter class="solr.IndonesianStemFilterFactory" stemDerivational="true"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Italian -->
|
||||
<fieldType name="text_it" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<!-- removes l', etc -->
|
||||
<filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_it.txt"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_it.txt" format="snowball" />
|
||||
<filter class="solr.ItalianLightStemFilterFactory"/>
|
||||
<!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="Italian"/> -->
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Japanese using morphological analysis (see text_cjk for a configuration using bigramming)
|
||||
|
||||
NOTE: If you want to optimize search for precision, use default operator AND in your query
|
||||
parser config with <solrQueryParser defaultOperator="AND"/> further down in this file. Use
|
||||
OR if you would like to optimize for recall (default).
|
||||
-->
|
||||
<fieldType name="text_ja" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="false">
|
||||
<analyzer>
|
||||
<!-- Kuromoji Japanese morphological analyzer/tokenizer (JapaneseTokenizer)
|
||||
|
||||
Kuromoji has a search mode (default) that does segmentation useful for search. A heuristic
|
||||
is used to segment compounds into its parts and the compound itself is kept as synonym.
|
||||
|
||||
Valid values for attribute mode are:
|
||||
normal: regular segmentation
|
||||
search: segmentation useful for search with synonyms compounds (default)
|
||||
extended: same as search mode, but unigrams unknown words (experimental)
|
||||
|
||||
For some applications it might be good to use search mode for indexing and normal mode for
|
||||
queries to reduce recall and prevent parts of compounds from being matched and highlighted.
|
||||
Use <analyzer type="index"> and <analyzer type="query"> for this and mode normal in query.
|
||||
|
||||
Kuromoji also has a convenient user dictionary feature that allows overriding the statistical
|
||||
model with your own entries for segmentation, part-of-speech tags and readings without a need
|
||||
to specify weights. Notice that user dictionaries have not been subject to extensive testing.
|
||||
|
||||
User dictionary attributes are:
|
||||
userDictionary: user dictionary filename
|
||||
userDictionaryEncoding: user dictionary encoding (default is UTF-8)
|
||||
|
||||
See lang/userdict_ja.txt for a sample user dictionary file.
|
||||
|
||||
Punctuation characters are discarded by default. Use discardPunctuation="false" to keep them.
|
||||
|
||||
See http://wiki.apache.org/solr/JapaneseLanguageSupport for more on Japanese language support.
|
||||
-->
|
||||
<tokenizer class="solr.JapaneseTokenizerFactory" mode="search"/>
|
||||
<!--<tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>-->
|
||||
<!-- Reduces inflected verbs and adjectives to their base/dictionary forms (~~~) -->
|
||||
<filter class="solr.JapaneseBaseFormFilterFactory"/>
|
||||
<!-- Removes tokens with certain part-of-speech tags -->
|
||||
<filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt" />
|
||||
<!-- Normalizes full-width romaji to half-width and half-width kana to full-width (Unicode NFKC subset) -->
|
||||
<filter class="solr.CJKWidthFilterFactory"/>
|
||||
<!-- Removes common tokens typically not useful for search, but have a negative effect on ranking -->
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt" />
|
||||
<!-- Normalizes common katakana spelling variations by removing any last long sound character (U+30FC) -->
|
||||
<filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
|
||||
<!-- Lower-cases romaji characters -->
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Latvian -->
|
||||
<fieldType name="text_lv" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_lv.txt" />
|
||||
<filter class="solr.LatvianStemFilterFactory"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Dutch -->
|
||||
<fieldType name="text_nl" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_nl.txt" format="snowball" />
|
||||
<filter class="solr.StemmerOverrideFilterFactory" dictionary="lang/stemdict_nl.txt" ignoreCase="false"/>
|
||||
<filter class="solr.SnowballPorterFilterFactory" language="Dutch"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Norwegian -->
|
||||
<fieldType name="text_no" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_no.txt" format="snowball" />
|
||||
<filter class="solr.SnowballPorterFilterFactory" language="Norwegian"/>
|
||||
<!-- less aggressive: <filter class="solr.NorwegianLightStemFilterFactory" variant="nb"/> -->
|
||||
<!-- singular/plural: <filter class="solr.NorwegianMinimalStemFilterFactory" variant="nb"/> -->
|
||||
<!-- The "light" and "minimal" stemmers support variants: nb=Bokml, nn=Nynorsk, no=Both -->
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Portuguese -->
|
||||
<fieldType name="text_pt" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_pt.txt" format="snowball" />
|
||||
<filter class="solr.PortugueseLightStemFilterFactory"/>
|
||||
<!-- less aggressive: <filter class="solr.PortugueseMinimalStemFilterFactory"/> -->
|
||||
<!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="Portuguese"/> -->
|
||||
<!-- most aggressive: <filter class="solr.PortugueseStemFilterFactory"/> -->
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Romanian -->
|
||||
<fieldType name="text_ro" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ro.txt" />
|
||||
<filter class="solr.SnowballPorterFilterFactory" language="Romanian"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Russian -->
|
||||
<fieldType name="text_ru" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ru.txt" format="snowball" />
|
||||
<filter class="solr.SnowballPorterFilterFactory" language="Russian"/>
|
||||
<!-- less aggressive: <filter class="solr.RussianLightStemFilterFactory"/> -->
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Swedish -->
|
||||
<fieldType name="text_sv" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_sv.txt" format="snowball" />
|
||||
<filter class="solr.SnowballPorterFilterFactory" language="Swedish"/>
|
||||
<!-- less aggressive: <filter class="solr.SwedishLightStemFilterFactory"/> -->
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Thai -->
|
||||
<fieldType name="text_th" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="org.apache.lucene.analysis.th.ThaiTokenizerFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_th.txt" />
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- Turkish -->
|
||||
<fieldType name="text_tr" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<!-- <filter class="solr.ApostropheFilterFactory"/> -->
|
||||
<filter class="solr.TurkishLowerCaseFilterFactory"/>
|
||||
<filter class="solr.StopFilterFactory" ignoreCase="false" words="lang/stopwords_tr.txt" />
|
||||
<filter class="solr.SnowballPorterFilterFactory" language="Turkish"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
|
||||
</types>
|
||||
<fields>
|
||||
<!-- For SOLR cloud - should be the node version -->
|
||||
<field name="_version_" type="version" indexed="false" stored="true" docValues="true" required="true" />
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- For block join - currently not used -->
|
||||
<field name="_root_" type="identifier" indexed="true" stored="false"/>
|
||||
|
||||
<!-- Unique identifier - based on DBID -->
|
||||
<field name="id" type="identifier" indexed="true" omitNorms="true" stored="true" multiValued="false" required="true" docValues="true"/>
|
||||
<field name="MINHASH" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" required="false" docValues="false"/>
|
||||
|
||||
<!-- Special fields -->
|
||||
<field name="LID" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<field name="PARENT" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<field name="PATH" type="path" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<field name="ANCESTOR" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<field name="QNAME" type="path" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<field name="PRIMARYASSOCQNAME" type="path" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<field name="PRIMARYASSOCTYPEQNAME" type="path" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<field name="ISNODE" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<field name="ASSOCTYPEQNAME" type="path" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<field name="PRIMARYPARENT" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<field name="TYPE" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="true" />
|
||||
<field name="ASPECT" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<field name="PROPERTIES" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<field name="NULLPROPERTIES" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<field name="FIELDS" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<field name="FTSSTATUS" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<field name="DBID" type="long" indexed="true" omitNorms="true" stored="true" multiValued="false" docValues="true" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<field name="TXID" type="long" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<field name="INTXID" type="long" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<field name="ACLTXID" type="long" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<field name="INACLTXID" type="long" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<field name="TXCOMMITTIME" type="long" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<field name="ACLTXCOMMITTIME" type="long" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<field name="EXCEPTIONMESSAGE" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<field name="EXCEPTIONSTACK" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<field name="ACLID" type="long" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<field name="READER" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<field name="DENIED" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<field name="OWNER" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<field name="PARENTASSOCCRC" type="long" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<field name="TENANT" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="true" />
|
||||
<field name="CASCADETX" type="long" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="false" sortMissingFirst="false" />
|
||||
|
||||
<!-- Used to store the last transaction and acl transaction for real time get -->
|
||||
<field name="S_TXID" type="long" indexed="true" omitNorms="true" stored="true" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<field name="S_INTXID" type="long" indexed="true" omitNorms="true" stored="true" multiValued="false" sortMissingLast="false" sortMissingFirst="false"/>
|
||||
<field name="S_ACLTXID" type="long" indexed="true" omitNorms="true" stored="true" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<field name="S_INACLTXID" type="long" indexed="true" omitNorms="true" stored="true" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<field name="S_TXCOMMITTIME" type="long" indexed="true" omitNorms="true" stored="true" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<field name="S_ACLTXCOMMITTIME" type="long" indexed="true" omitNorms="true" stored="true" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
|
||||
<!-- SOLR doc type -->
|
||||
<field name="DOC_TYPE" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
|
||||
<!-- GEO -->
|
||||
<field name="GEO" type="location_rpt" indexed="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
|
||||
|
||||
|
||||
<!-- Suggestion -->
|
||||
<field name="suggest" type="text_shingle" indexed="true" omitNorms="true" omitPositions="true" stored="false" multiValued="true" />
|
||||
<field name="min_hash" type="text_min_hash" indexed="true" omitNorms="true" omitPositions="true" stored="false" multiValued="true" />
|
||||
|
||||
<!-- Dummy field used to create no matches for unknonw properties -->
|
||||
<field name="_dummy_" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
|
||||
|
||||
<!-- example pluggable field -->
|
||||
<field name="SITE" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<field name="TAG" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<field name="PNAME" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<field name="NPATH" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<field name="ANAME" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<field name="APATH" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Single value indexed -->
|
||||
<dynamicField name="any@s_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<dynamicField name="encrypted@s_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<dynamicField name="int@s_@*" type="int" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<dynamicField name="long@s_@*" type="long" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<dynamicField name="float@s_@*" type="float" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<dynamicField name="double@s_@*" type="double" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<dynamicField name="date@s_@*" type="date" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<dynamicField name="datetime@s_@*" type="date" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<dynamicField name="boolean@s_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<dynamicField name="qname@s_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<dynamicField name="category@s_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<dynamicField name="noderef@s_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<dynamicField name="noderef@sd_@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" sortMissingLast="true" />
|
||||
<dynamicField name="childassocref@s_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<dynamicField name="assocref@s_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<dynamicField name="path@s_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<dynamicField name="locale@s_@*" type="lowercase_id" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<dynamicField name="period@s_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
|
||||
<!-- Single + doc values value wildcard matches -->
|
||||
<dynamicField name="int@sd@*" type="int" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<dynamicField name="long@sd@*" type="long" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<dynamicField name="float@sd@*" type="float" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<dynamicField name="double@sd@*" type="double" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<dynamicField name="date@sd@*" type="date" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<dynamicField name="datetime@sd@*" type="date" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="false" sortMissingFirst="false" />
|
||||
|
||||
|
||||
<!-- Multi - value indexed -->
|
||||
<dynamicField name="any@m_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="encrypted@m_@*" type="alfrescoFieldType" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="int@m_@*" type="int" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="long@m_@*" type="long" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="float@m_@*" type="float" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="double@m_@*" type="double" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="date@m_@*" type="date" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="datetime@m_@*" type="date" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="boolean@m_@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="boolean@md_@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" sortMissingLast="true"/>
|
||||
<dynamicField name="qname@m_@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="qname@md_@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" sortMissingLast="true"/>
|
||||
<dynamicField name="category@m_@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="category@md_@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" sortMissingLast="true" />
|
||||
<dynamicField name="category@sd_@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="true" />
|
||||
<dynamicField name="noderef@m_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="noderef@md@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" sortMissingLast="true" />
|
||||
<dynamicField name="childassocref@m_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="assocref@m_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="path@m_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="locale@m_@*" type="lowercase_id" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="period@m_@*" type="oldStandardAnalysis" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
|
||||
<!-- Multi + doc values value wildcard matches -->
|
||||
<dynamicField name="int@md@*" type="int" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<dynamicField name="long@md@*" type="long" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<dynamicField name="float@md@*" type="float" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<dynamicField name="double@md@*" type="double" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<dynamicField name="date@md@*" type="date" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<dynamicField name="datetime@md@*" type="date" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
|
||||
|
||||
<dynamicField name="text@s____@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<dynamicField name="text@s__l_@*" type="alfrescoFieldType" indexed="true" omitNorms="true" stored="false" multiValued="false" />
|
||||
<dynamicField name="text@s__lt@*" type="alfrescoFieldType" indexed="true" omitNorms="false" stored="false" multiValued="false" />
|
||||
<dynamicField name="text@s___t@*" type="text___" indexed="true" omitNorms="false" stored="false" multiValued="false" />
|
||||
<dynamicField name="text@s__sort@*" type="alfrescoCollatableTextFieldType" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
|
||||
<dynamicField name="text@sd___@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="true" />
|
||||
|
||||
<dynamicField name="text@m____@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="text@m__l_@*" type="alfrescoFieldType" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="text@m__lt@*" type="alfrescoFieldType" indexed="true" omitNorms="false" stored="false" multiValued="true" />
|
||||
<dynamicField name="text@m___t@*" type="text___" indexed="true" omitNorms="false" stored="false" multiValued="true" />
|
||||
|
||||
<dynamicField name="text@md___@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
|
||||
<dynamicField name="mltext@m____@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="mltext@m__l_@*" type="alfrescoFieldType" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="mltext@m__lt@*" type="alfrescoFieldType" indexed="true" omitNorms="false" stored="false" multiValued="true" />
|
||||
<dynamicField name="mltext@m___t@*" type="text___" indexed="true" omitNorms="false" stored="false" multiValued="true" />
|
||||
<dynamicField name="mltext@m__sort@*" type="alfrescoCollatableMLTextFieldType" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
|
||||
<dynamicField name="content@s__size@*" type="long" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<dynamicField name="content@s__locale@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="true" />
|
||||
<dynamicField name="content@s__mimetype@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="true" />
|
||||
<dynamicField name="content@s__encoding@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="true" />
|
||||
<dynamicField name="content@s__docid@*" type="long" indexed="true" omitNorms="true" stored="false" multiValued="false" docValues="true" sortMissingLast="false" sortMissingFirst="false" />
|
||||
<dynamicField name="content@s__tr_ex@*" type="text___" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<dynamicField name="content@s__tr_time@*" type="long" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
<dynamicField name="content@s__tr_status@*" type="lowercase_id" indexed="true" omitNorms="true" stored="false" multiValued="false" sortMissingLast="true" />
|
||||
|
||||
|
||||
<dynamicField name="content@s____@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="false" termPositions="false" />
|
||||
<dynamicField name="content@s__l_@*" type="alfrescoFieldType" indexed="true" omitNorms="true" stored="false" multiValued="false" termPositions="false" />
|
||||
<dynamicField name="content@s__lt@*" type="alfrescoFieldType" indexed="true" omitNorms="false" stored="false" multiValued="false" />
|
||||
<dynamicField name="content@s___t@*" type="text___" indexed="true" omitNorms="false" stored="false" multiValued="false" />
|
||||
|
||||
|
||||
<dynamicField name="content@m__size@*" type="long" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<dynamicField name="content@m__locale@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<dynamicField name="content@m__mimetype@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<dynamicField name="content@m__encoding@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<dynamicField name="content@m__docid@*" type="long" indexed="true" omitNorms="true" stored="false" multiValued="true" docValues="true" />
|
||||
<dynamicField name="content@m__tr_ex@*" type="text___" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="content@m__tr_time@*" type="long" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
<dynamicField name="content@m__tr_status@*" type="lowercase_id" indexed="true" omitNorms="true" stored="false" multiValued="true" />
|
||||
|
||||
|
||||
<dynamicField name="content@m____@*" type="identifier" indexed="true" omitNorms="true" stored="false" multiValued="true" termPositions="false" />
|
||||
<dynamicField name="content@m__l_@*" type="alfrescoFieldType" indexed="true" omitNorms="true" stored="false" multiValued="true" termPositions="false" />
|
||||
<dynamicField name="content@m__lt@*" type="alfrescoFieldType" indexed="true" omitNorms="false" stored="false" multiValued="true" />
|
||||
<dynamicField name="content@m___t@*" type="text___" indexed="true" omitNorms="false" stored="false" multiValued="true" />
|
||||
|
||||
|
||||
<!-- Suggestion -->
|
||||
<dynamicField name="suggest_*" type="text_shingle" indexed="false" omitNorms="true" stored="false" multiValued="true" />
|
||||
|
||||
<copyField source="suggest_*" dest="suggest" />
|
||||
|
||||
</fields>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
</schema>
|
||||
Reference in New Issue
Block a user