Skip to content

Commit a36773b

Browse files
authored
Merge pull request #1641 from marklogic/feature/1640-bug
Added test for and-not query
2 parents fe5d97d + acb5085 commit a36773b

File tree

1 file changed

+218
-146
lines changed

1 file changed

+218
-146
lines changed

marklogic-client-api/src/test/java/com/marklogic/client/test/StructuredSearchTest.java

Lines changed: 218 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -15,168 +15,240 @@
1515
*/
1616
package com.marklogic.client.test;
1717

18+
import com.marklogic.client.datamovement.DataMovementManager;
19+
import com.marklogic.client.datamovement.QueryBatcher;
20+
import com.marklogic.client.document.DocumentWriteSet;
1821
import com.marklogic.client.document.GenericDocumentManager;
22+
import com.marklogic.client.document.XMLDocumentManager;
23+
import com.marklogic.client.io.DocumentMetadataHandle;
1924
import com.marklogic.client.io.Format;
2025
import com.marklogic.client.io.SearchHandle;
2126
import com.marklogic.client.io.StringHandle;
2227
import com.marklogic.client.query.*;
2328
import com.marklogic.client.util.EditableNamespaceContext;
24-
import org.junit.jupiter.api.AfterAll;
2529
import org.junit.jupiter.api.BeforeAll;
2630
import org.junit.jupiter.api.Test;
2731
import org.w3c.dom.Document;
2832
import org.w3c.dom.Element;
2933
import org.xml.sax.SAXException;
3034

3135
import java.io.IOException;
36+
import java.util.concurrent.atomic.AtomicInteger;
3237

3338
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
3439
import static org.junit.jupiter.api.Assertions.*;
3540

3641
public class StructuredSearchTest {
37-
@BeforeAll
38-
public static void beforeClass() {
39-
Common.connect();
40-
}
41-
42-
@AfterAll
43-
public static void afterClass() {
44-
}
45-
46-
@Test
47-
public void testStructuredSearch() throws IOException {
48-
QueryManager queryMgr = Common.client.newQueryManager();
49-
StructuredQueryBuilder qb = queryMgr.newStructuredQueryBuilder();
50-
51-
for (QueryDefinition t:new QueryDefinition[]{
52-
qb.term("leaf3"), qb.build(qb.value(qb.element("leaf"), "leaf3"))
53-
}) {
54-
SearchHandle results = queryMgr.search(t, new SearchHandle());
55-
assertNotNull(results);
56-
assertFalse(results.getMetrics().getTotalTime() == -1);
57-
58-
MatchDocumentSummary[] summaries = results.getMatchResults();
59-
assertNotNull(summaries);
60-
assertEquals( 1, summaries.length);
61-
for (MatchDocumentSummary summary : summaries) {
62-
MatchLocation[] locations = summary.getMatchLocations();
63-
assertEquals( 1, locations.length);
64-
for (MatchLocation location : locations) {
65-
assertNotNull(location.getAllSnippetText());
66-
}
67-
}
68-
}
69-
}
70-
71-
@Test
72-
public void testStructuredSearch1() throws IOException {
73-
QueryManager queryMgr = Common.client.newQueryManager();
74-
StructuredQueryBuilder qb = queryMgr.newStructuredQueryBuilder();
75-
76-
for (QueryDefinition t:new QueryDefinition[]{
77-
qb.term("leaf3"), qb.build(qb.value(qb.element("leaf"), "leaf3"))
78-
}) {
79-
80-
MatchDocumentSummary summary = queryMgr.findOne(t);
81-
assertNotNull(summary);
82-
83-
GenericDocumentManager docMgr = Common.client.newDocumentManager();
84-
assertNotNull( docMgr.exists(summary.getUri()));
85-
}
86-
}
87-
88-
@Test
89-
public void testStructuredSearch2() throws IOException {
90-
QueryManager queryMgr = Common.client.newQueryManager();
91-
92-
EditableNamespaceContext namespaces = new EditableNamespaceContext();
93-
namespaces.put("x", "root.org");
94-
namespaces.put("y", "target.org");
95-
StructuredQueryBuilder qb = new StructuredQueryBuilder(namespaces);
96-
97-
StructuredQueryDefinition qdef = qb.geospatial(
98-
qb.geoPath(qb.pathIndex("/x:geo/y:path")),
99-
qb.box(1, 2, 3, 4));
100-
101-
SearchHandle results = queryMgr.search(qdef, new SearchHandle());
102-
assertNotNull(results);
103-
104-
MatchDocumentSummary[] summaries = results.getMatchResults();
105-
assertTrue(summaries == null || summaries.length == 0);
106-
}
107-
108-
109-
@Test
110-
public void testFailedSearch() throws IOException {
111-
QueryManager queryMgr = Common.client.newQueryManager();
112-
StructuredQueryBuilder qb = queryMgr.newStructuredQueryBuilder();
113-
StructuredQueryDefinition qdef = qb.term(
114-
"criteriaThatShouldNotMatchAnyDocument");
115-
116-
SearchHandle results = queryMgr.search(qdef, new SearchHandle());
117-
assertNotNull(results);
118-
119-
MatchDocumentSummary[] summaries = results.getMatchResults();
120-
assertTrue(summaries == null || summaries.length == 0);
121-
}
122-
123-
@Test
124-
public void testJSON() {
125-
QueryManager queryMgr = Common.client.newQueryManager();
126-
StructuredQueryBuilder qb = queryMgr.newStructuredQueryBuilder();
127-
StructuredQueryDefinition t = qb.term("leaf3");
128-
129-
// create a handle for the search results
130-
StringHandle resultsHandle = new StringHandle().withFormat(Format.JSON);
131-
132-
// run the search
133-
queryMgr.search(t, resultsHandle);
134-
135-
assertEquals("{", resultsHandle.get().substring(0, 1)); // It's JSON, right?
136-
}
137-
138-
@Test
139-
public void testExtractMetadata() throws SAXException, IOException {
140-
QueryManager queryMgr = Common.client.newQueryManager();
141-
142-
String combined =
143-
"<search xmlns=\"http://marklogic.com/appservices/search\">"+
144-
"<query>"+
145-
"<value-query>"+
146-
"<element ns=\"http://marklogic.com/xdmp/json\" name=\"firstKey\"/>"+
147-
"<text>first value</text>"+
148-
"</value-query>"+
149-
"</query>"+
150-
"<options>"+
151-
"<extract-metadata>"+
152-
"<qname elem-ns=\"http://marklogic.com/xdmp/json\" elem-name=\"subKey\"/>"+
153-
"</extract-metadata>"+
154-
"</options>"+
155-
"</search>";
156-
StringHandle rawHandle = new StringHandle(combined);
157-
158-
RawCombinedQueryDefinition rawDef = queryMgr.newRawCombinedQueryDefinition(rawHandle);
159-
160-
SearchHandle sh = queryMgr.search(rawDef, new SearchHandle());
161-
162-
MatchDocumentSummary[] summaries = sh.getMatchResults();
163-
assertNotNull(summaries);
164-
assertEquals( 1, summaries.length);
165-
166-
MatchDocumentSummary matchResult = summaries[0];
167-
Document metadata = matchResult.getMetadata();
168-
Element subKey = (Element)
169-
metadata.getElementsByTagNameNS("http://marklogic.com/xdmp/json", "subKey").item(0);
170-
assertEquals("string", subKey.getAttribute("type"));
171-
assertEquals("sub value", subKey.getTextContent());
172-
173-
String docStr = Common.testDocumentToString(metadata);
174-
String handleStr = matchResult.getMetadata(new StringHandle()).get();
175-
assertXMLEqual("Different metadata for handle", docStr, handleStr);
176-
177-
Document snippet = matchResult.getSnippets()[0];
178-
docStr = Common.testDocumentToString(snippet);
179-
handleStr = matchResult.getSnippetIterator(new StringHandle()).next().get();
180-
assertXMLEqual("Different snippet for handle", docStr, handleStr);
181-
}
42+
43+
@BeforeAll
44+
public static void beforeClass() {
45+
Common.connect();
46+
}
47+
48+
@Test
49+
public void testStructuredSearch() {
50+
QueryManager queryMgr = Common.client.newQueryManager();
51+
StructuredQueryBuilder qb = queryMgr.newStructuredQueryBuilder();
52+
53+
for (QueryDefinition t : new QueryDefinition[]{
54+
qb.term("leaf3"), qb.build(qb.value(qb.element("leaf"), "leaf3"))
55+
}) {
56+
SearchHandle results = queryMgr.search(t, new SearchHandle());
57+
assertNotNull(results);
58+
assertFalse(results.getMetrics().getTotalTime() == -1);
59+
60+
MatchDocumentSummary[] summaries = results.getMatchResults();
61+
assertNotNull(summaries);
62+
assertEquals(1, summaries.length);
63+
for (MatchDocumentSummary summary : summaries) {
64+
MatchLocation[] locations = summary.getMatchLocations();
65+
assertEquals(1, locations.length);
66+
for (MatchLocation location : locations) {
67+
assertNotNull(location.getAllSnippetText());
68+
}
69+
}
70+
}
71+
}
72+
73+
@Test
74+
public void testStructuredSearch1() {
75+
QueryManager queryMgr = Common.client.newQueryManager();
76+
StructuredQueryBuilder qb = queryMgr.newStructuredQueryBuilder();
77+
78+
for (QueryDefinition t : new QueryDefinition[]{
79+
qb.term("leaf3"), qb.build(qb.value(qb.element("leaf"), "leaf3"))
80+
}) {
81+
82+
MatchDocumentSummary summary = queryMgr.findOne(t);
83+
assertNotNull(summary);
84+
85+
GenericDocumentManager docMgr = Common.client.newDocumentManager();
86+
assertNotNull(docMgr.exists(summary.getUri()));
87+
}
88+
}
89+
90+
@Test
91+
public void testStructuredSearch2() {
92+
QueryManager queryMgr = Common.client.newQueryManager();
93+
94+
EditableNamespaceContext namespaces = new EditableNamespaceContext();
95+
namespaces.put("x", "root.org");
96+
namespaces.put("y", "target.org");
97+
StructuredQueryBuilder qb = new StructuredQueryBuilder(namespaces);
98+
99+
StructuredQueryDefinition qdef = qb.geospatial(
100+
qb.geoPath(qb.pathIndex("/x:geo/y:path")),
101+
qb.box(1, 2, 3, 4));
102+
103+
SearchHandle results = queryMgr.search(qdef, new SearchHandle());
104+
assertNotNull(results);
105+
106+
MatchDocumentSummary[] summaries = results.getMatchResults();
107+
assertTrue(summaries == null || summaries.length == 0);
108+
}
109+
110+
111+
@Test
112+
public void testFailedSearch() {
113+
QueryManager queryMgr = Common.client.newQueryManager();
114+
StructuredQueryBuilder qb = queryMgr.newStructuredQueryBuilder();
115+
StructuredQueryDefinition qdef = qb.term(
116+
"criteriaThatShouldNotMatchAnyDocument");
117+
118+
SearchHandle results = queryMgr.search(qdef, new SearchHandle());
119+
assertNotNull(results);
120+
121+
MatchDocumentSummary[] summaries = results.getMatchResults();
122+
assertTrue(summaries == null || summaries.length == 0);
123+
}
124+
125+
@Test
126+
public void testJSON() {
127+
QueryManager queryMgr = Common.client.newQueryManager();
128+
StructuredQueryBuilder qb = queryMgr.newStructuredQueryBuilder();
129+
StructuredQueryDefinition t = qb.term("leaf3");
130+
131+
// create a handle for the search results
132+
StringHandle resultsHandle = new StringHandle().withFormat(Format.JSON);
133+
134+
// run the search
135+
queryMgr.search(t, resultsHandle);
136+
137+
assertEquals("{", resultsHandle.get().substring(0, 1)); // It's JSON, right?
138+
}
139+
140+
@Test
141+
public void testExtractMetadata() throws SAXException, IOException {
142+
QueryManager queryMgr = Common.client.newQueryManager();
143+
144+
String combined =
145+
"<search xmlns=\"http://marklogic.com/appservices/search\">" +
146+
"<query>" +
147+
"<value-query>" +
148+
"<element ns=\"http://marklogic.com/xdmp/json\" name=\"firstKey\"/>" +
149+
"<text>first value</text>" +
150+
"</value-query>" +
151+
"</query>" +
152+
"<options>" +
153+
"<extract-metadata>" +
154+
"<qname elem-ns=\"http://marklogic.com/xdmp/json\" elem-name=\"subKey\"/>" +
155+
"</extract-metadata>" +
156+
"</options>" +
157+
"</search>";
158+
StringHandle rawHandle = new StringHandle(combined);
159+
160+
RawCombinedQueryDefinition rawDef = queryMgr.newRawCombinedQueryDefinition(rawHandle);
161+
162+
SearchHandle sh = queryMgr.search(rawDef, new SearchHandle());
163+
164+
MatchDocumentSummary[] summaries = sh.getMatchResults();
165+
assertNotNull(summaries);
166+
assertEquals(1, summaries.length);
167+
168+
MatchDocumentSummary matchResult = summaries[0];
169+
Document metadata = matchResult.getMetadata();
170+
Element subKey = (Element)
171+
metadata.getElementsByTagNameNS("http://marklogic.com/xdmp/json", "subKey").item(0);
172+
assertEquals("string", subKey.getAttribute("type"));
173+
assertEquals("sub value", subKey.getTextContent());
174+
175+
String docStr = Common.testDocumentToString(metadata);
176+
String handleStr = matchResult.getMetadata(new StringHandle()).get();
177+
assertXMLEqual("Different metadata for handle", docStr, handleStr);
178+
179+
Document snippet = matchResult.getSnippets()[0];
180+
docStr = Common.testDocumentToString(snippet);
181+
handleStr = matchResult.getSnippetIterator(new StringHandle()).next().get();
182+
assertXMLEqual("Different snippet for handle", docStr, handleStr);
183+
}
184+
185+
@Test
186+
void andNotQuery() {
187+
QueryManager queryManager = Common.client.newQueryManager();
188+
189+
// Write the same doc in 2 different collections.
190+
XMLDocumentManager mgr = Common.client.newXMLDocumentManager();
191+
DocumentWriteSet writeSet = mgr.newWriteSet();
192+
writeSet.add("/1.xml", new DocumentMetadataHandle()
193+
.withPermission("rest-reader", DocumentMetadataHandle.Capability.READ, DocumentMetadataHandle.Capability.UPDATE)
194+
.withCollections("test1"), new StringHandle("<hello>world</hello>"));
195+
writeSet.add("/2.xml", new DocumentMetadataHandle()
196+
.withPermission("rest-reader", DocumentMetadataHandle.Capability.READ, DocumentMetadataHandle.Capability.UPDATE)
197+
.withCollections("test2"), new StringHandle("<hello>world</hello>"));
198+
mgr.write(writeSet);
199+
200+
// Verify a structured query works
201+
StructuredQueryBuilder queryBuilder = queryManager.newStructuredQueryBuilder();
202+
StructuredQueryDefinition structuredQuery = queryBuilder.and(
203+
queryBuilder.term("world"),
204+
queryBuilder.andNot(
205+
queryBuilder.collection("test1"),
206+
queryBuilder.collection("test2")
207+
)
208+
);
209+
210+
long count = queryManager.search(structuredQuery, new SearchHandle()).getTotalResults();
211+
assertEquals(1, count);
212+
213+
// Verify a combined query works.
214+
String combinedQuery = "<search xmlns=\"http://marklogic.com/appservices/search\">\n" +
215+
" <query>\n" +
216+
" <and-query>\n" +
217+
" <term-query>\n" +
218+
" <text>world</text>\n" +
219+
" </term-query>\n" +
220+
" <and-not-query>\n" +
221+
" <positive-query>\n" +
222+
" <collection-query>\n" +
223+
" <uri>test1</uri>\n" +
224+
" </collection-query>\n" +
225+
" </positive-query>\n" +
226+
" <negative-query>\n" +
227+
" <collection-query>\n" +
228+
" <uri>test2</uri>\n" +
229+
" </collection-query>\n" +
230+
" </negative-query>\n" +
231+
" </and-not-query>\n" +
232+
" </and-query>\n" +
233+
" </query>\n" +
234+
"</search>";
235+
236+
count = queryManager.search(
237+
queryManager.newRawCombinedQueryDefinition(new StringHandle(combinedQuery)),
238+
new SearchHandle()).getTotalResults();
239+
assertEquals(1, count);
240+
241+
// Verify the combined query works with DMSDK.
242+
DataMovementManager dmm = Common.client.newDataMovementManager();
243+
AtomicInteger counter = new AtomicInteger();
244+
QueryBatcher qb = dmm.newQueryBatcher(
245+
queryManager.newRawCombinedQueryDefinition(new StringHandle(combinedQuery))
246+
)
247+
.onUrisReady(batch -> counter.getAndAdd(batch.getItems().length))
248+
.withThreadCount(1);
249+
dmm.startJob(qb);
250+
qb.awaitCompletion();
251+
dmm.stopJob(qb);
252+
assertEquals(1, counter.get());
253+
}
182254
}

0 commit comments

Comments
 (0)