|
15 | 15 | */ |
16 | 16 | package com.marklogic.client.test; |
17 | 17 |
|
| 18 | +import com.marklogic.client.datamovement.DataMovementManager; |
| 19 | +import com.marklogic.client.datamovement.QueryBatcher; |
| 20 | +import com.marklogic.client.document.DocumentWriteSet; |
18 | 21 | import com.marklogic.client.document.GenericDocumentManager; |
| 22 | +import com.marklogic.client.document.XMLDocumentManager; |
| 23 | +import com.marklogic.client.io.DocumentMetadataHandle; |
19 | 24 | import com.marklogic.client.io.Format; |
20 | 25 | import com.marklogic.client.io.SearchHandle; |
21 | 26 | import com.marklogic.client.io.StringHandle; |
22 | 27 | import com.marklogic.client.query.*; |
23 | 28 | import com.marklogic.client.util.EditableNamespaceContext; |
24 | | -import org.junit.jupiter.api.AfterAll; |
25 | 29 | import org.junit.jupiter.api.BeforeAll; |
26 | 30 | import org.junit.jupiter.api.Test; |
27 | 31 | import org.w3c.dom.Document; |
28 | 32 | import org.w3c.dom.Element; |
29 | 33 | import org.xml.sax.SAXException; |
30 | 34 |
|
31 | 35 | import java.io.IOException; |
| 36 | +import java.util.concurrent.atomic.AtomicInteger; |
32 | 37 |
|
33 | 38 | import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; |
34 | 39 | import static org.junit.jupiter.api.Assertions.*; |
35 | 40 |
|
36 | 41 | 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 | + } |
182 | 254 | } |
0 commit comments