use of org.exist.dom.persistent.NodeSet in project exist by eXist-db.
the class FieldLookup method eval.
@Override
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
if (contextItem != null)
contextSequence = contextItem.toSequence();
if (contextSequence != null && !contextSequence.isPersistentSet())
// in-memory docs won't have an index
if (fallback == null) {
return Sequence.EMPTY_SEQUENCE;
} else {
return fallback.eval(contextSequence, contextItem);
}
NodeSet result;
if (preselectResult == null) {
long start = System.currentTimeMillis();
DocumentSet docs;
if (contextSequence == null)
docs = context.getStaticallyKnownDocuments();
else
docs = contextSequence.getDocumentSet();
NodeSet contextSet = null;
if (contextSequence != null)
contextSet = contextSequence.toNodeSet();
Sequence fields = getArgument(0).eval(contextSequence);
RangeIndex.Operator[] operators = null;
int j = 1;
if (isCalledAs("field")) {
Sequence operatorSeq = getArgument(1).eval(contextSequence);
operators = new RangeIndex.Operator[operatorSeq.getItemCount()];
int i = 0;
for (SequenceIterator si = operatorSeq.iterate(); si.hasNext(); i++) {
operators[i] = RangeIndexModule.OPERATOR_MAP.get(si.nextItem().getStringValue());
}
j++;
} else {
RangeIndex.Operator operator = getOperator();
operators = new RangeIndex.Operator[fields.getItemCount()];
Arrays.fill(operators, operator);
}
if (operators.length != fields.getItemCount()) {
throw new XPathException(this, "Number of operators specified must correspond to number of fields queried");
}
Sequence[] keys = new Sequence[getArgumentCount() - j];
SequenceIterator fieldIter = fields.unorderedIterator();
for (int i = j; i < getArgumentCount(); i++) {
keys[i - j] = getArgument(i).eval(contextSequence);
int targetType = Type.ITEM;
if (fieldIter.hasNext()) {
String field = fieldIter.nextItem().getStringValue();
targetType = getType(contextSequence, field);
}
if (targetType != Type.ITEM && !Type.subTypeOf(keys[i - j].getItemType(), targetType)) {
if (keys[i - j].hasMany()) {
final Sequence temp = new ValueSequence(keys[i - j].getItemCount());
for (final SequenceIterator iterator = keys[i - j].unorderedIterator(); iterator.hasNext(); ) {
temp.add(iterator.nextItem().convertTo(targetType));
}
keys[i - j] = temp;
} else {
keys[i - j] = keys[i - j].convertTo(targetType);
}
}
}
if (keys.length < fields.getItemCount()) {
throw new XPathException(this, "Number of keys to look up must correspond to number of fields specified");
}
RangeIndexWorker index = (RangeIndexWorker) context.getBroker().getIndexController().getWorkerByIndexId(RangeIndex.ID);
try {
result = index.queryField(getExpressionId(), docs, contextSet, fields, keys, operators, NodeSet.DESCENDANT);
if (contextSet != null) {
if (fallback != null && (fallback.getPrimaryAxis() == Constants.CHILD_AXIS || fallback.getPrimaryAxis() == Constants.ATTRIBUTE_AXIS)) {
result = result.selectParentChild(contextSet, NodeSet.DESCENDANT, getContextId());
} else {
result = result.selectAncestorDescendant(contextSet, NodeSet.DESCENDANT, true, getContextId(), true);
}
}
} catch (IOException e) {
throw new XPathException(this, e.getMessage());
}
if (context.getProfiler().traceFunctions()) {
context.getProfiler().traceIndexUsage(context, "new-range", this, PerformanceStats.OPTIMIZED_INDEX, System.currentTimeMillis() - start);
}
// LOG.info("eval plain took " + (System.currentTimeMillis() - start));
} else {
result = preselectResult.selectAncestorDescendant(contextSequence.toNodeSet(), NodeSet.DESCENDANT, true, getContextId(), true);
}
return result;
}
use of org.exist.dom.persistent.NodeSet in project exist by eXist-db.
the class RangeIndexWorker method queryField.
public NodeSet queryField(int contextId, DocumentSet docs, NodeSet contextSet, Sequence fields, Sequence[] keys, RangeIndex.Operator[] operators, int axis) throws IOException, XPathException {
return index.withSearcher(searcher -> {
BooleanQuery query = new BooleanQuery();
int j = 0;
for (SequenceIterator i = fields.iterate(); i.hasNext(); j++) {
String field = i.nextItem().getStringValue();
if (keys[j].getItemCount() > 1) {
BooleanQuery bool = new BooleanQuery();
bool.setMinimumNumberShouldMatch(1);
for (SequenceIterator ki = keys[j].iterate(); ki.hasNext(); ) {
Item key = ki.nextItem();
Query q = toQuery(field, null, key.atomize(), operators[j], docs);
bool.add(q, BooleanClause.Occur.SHOULD);
}
query.add(bool, BooleanClause.Occur.MUST);
} else {
Query q = toQuery(field, null, keys[j].itemAt(0).atomize(), operators[j], docs);
query.add(q, BooleanClause.Occur.MUST);
}
}
Query qu = query;
BooleanClause[] clauses = query.getClauses();
if (clauses.length == 1) {
qu = clauses[0].getQuery();
}
final NodeSet resultSet = new NewArrayNodeSet();
resultSet.addAll(doQuery(contextId, docs, contextSet, axis, searcher.searcher, Node.ELEMENT_NODE, qu, null));
return resultSet;
});
}
use of org.exist.dom.persistent.NodeSet in project exist by eXist-db.
the class RangeIndexWorker method query.
public NodeSet query(int contextId, DocumentSet docs, NodeSet contextSet, List<QName> qnames, AtomicValue[] keys, RangeIndex.Operator operator, int axis) throws IOException, XPathException {
return index.withSearcher(searcher -> {
List<QName> definedIndexes = getDefinedIndexes(qnames);
NodeSet resultSet = new NewArrayNodeSet();
for (QName qname : definedIndexes) {
Query query;
String field = LuceneUtil.encodeQName(qname, index.getBrokerPool().getSymbols());
if (keys.length > 1) {
BooleanQuery bool = new BooleanQuery();
for (AtomicValue key : keys) {
bool.add(toQuery(field, qname, key, operator, docs), BooleanClause.Occur.SHOULD);
}
query = bool;
} else {
query = toQuery(field, qname, keys[0], operator, docs);
}
final short nodeType = qname.getNameType() == ElementValue.ATTRIBUTE ? Node.ATTRIBUTE_NODE : Node.ELEMENT_NODE;
resultSet.addAll(doQuery(contextId, docs, contextSet, axis, searcher.searcher, nodeType, query, null));
}
return resultSet;
});
}
use of org.exist.dom.persistent.NodeSet in project exist by eXist-db.
the class WildcardedExpressionTriple method eval.
@Override
public NodeSet eval(final NGramIndexWorker index, final DocumentSet docs, final List<QName> qnames, final NodeSet nodeSet, final int axis, final int expressionId) throws XPathException {
final NodeSet headNodes = head.eval(index, docs, qnames, nodeSet, axis, expressionId);
if (headNodes.isEmpty()) {
return headNodes;
}
final NodeSet tailNodes = tail.eval(index, docs, qnames, nodeSet, axis, expressionId);
if (tailNodes.isEmpty()) {
return tailNodes;
}
final NodeSet result = NodeSets.transformNodes(headNodes, headNode -> Optional.ofNullable(tailNodes.get(headNode)).map(tailNode -> getMatchingNode(headNode, tailNode, expressionId)).orElse(null));
return result;
}
use of org.exist.dom.persistent.NodeSet in project exist by eXist-db.
the class NodeSets method transformNodes.
/**
* Builds a new NodeSet by applying a function to all NodeProxys of the supplied NodeSet and returning all non-null
* results.
*
* @param nodes
* the NodeSet containig the NodeProys to be transformed
* @param transform
* the function to be applied to all NodeProxys in nodes
* @return a new NodeSet containing the non-null results of f applied to the NodeProxys in nodes
*
* @throws XPathException if an error occurs with the query.
*/
public static NodeSet transformNodes(final NodeSet nodes, final Function<NodeProxy, NodeProxy> transform) throws XPathException {
final NodeSet result = new ExtArrayNodeSet();
for (NodeProxy nodeProxy : nodes) {
final NodeProxy node = transform.apply(nodeProxy);
if (node != null) {
result.add(node);
}
}
// ensure result is ready to use
result.iterate();
return result;
}
Aggregations