1 package search.db;
2 
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.List;
6 import java.util.Set;
7 import java.util.TreeSet;
8 
9 import util.ConnectionUtil;
10import util.TableOperations;
11import chemaxon.jchem.db.JChemSearch;
12import chemaxon.sss.SearchConstants;
13import chemaxon.sss.search.JChemSearchOptions;
14import chemaxon.util.ConnectionHandler;
15
16/**
17 * This class demonstrates two different approaches to retrieve the intersection of the result
18 * of multiple queries (logical AND operation).
19 * 
20 * @author JChem Base team, ChemAxon Ltd.
21 */
22public final class MultipleQueriesExample {
23
24    private static final String TABLE_NAME = "demo";
25
26    private static final String[] QUERIES = new String[] { "CCCCC", "O", "N" };
27
28    private ConnectionHandler connHandler;
29
30    public static void main(String[] args) {
31        try {
32            new MultipleQueriesExample().run();
33        } catch (Exception e) {
34            e.printStackTrace();
35        }
36    }
37
38    private void run() throws Exception {
39        connHandler = ConnectionUtil.connectToDB();
40        try {
41            TableOperations.setupMoleculeTable(connHandler, TABLE_NAME);
42            warmupSearch();
43            runNormalQueries();
44            runFilteredQueries();
45        } finally {
46            ConnectionUtil.closeConnection(connHandler);
47        }
48    }
49
50    /**
51     * Executes the queries separately and calculates the intersection of the returned cd_ids
52     * "manually".
53     */
54    private void runNormalQueries() throws Exception {
55
56        System.out.println("Running normal queries");
57
58        long start = System.currentTimeMillis();
59
60        Set<Integer> results = new TreeSet<Integer>(getSearchHits(QUERIES[0]));
61        results.retainAll(getSearchHits(QUERIES[1]));
62        results.retainAll(getSearchHits(QUERIES[2]));
63
64        System.out.println("Final results:");
65        System.out.println("Elapsed time (in ms): " + (System.currentTimeMillis() - start));
66        listResults(results);
67    }
68
69    /**
70     * Executes the queries with passing the cd_ids of the result of the previous query to the
71     * next JChem search as filter criterion.
72     */
73    private void runFilteredQueries() throws Exception {
74
75        System.out.println("Running filtered queries");
76
77        long start = System.currentTimeMillis();
78        Collection<Integer> results = getSearchHits(QUERIES[0]);
79        results = getFilteredSearchHits(QUERIES[1], results);
80        results = getFilteredSearchHits(QUERIES[2], results);
81
82        System.out.println("Final results:");
83        System.out.println("Elapsed time (in ms): " + (System.currentTimeMillis() - start));
84        listResults(results);
85    }
86
87    /**
88     * Get hits for a database search without filter ids.
89     * 
90     * @param query the query string
91     * @return the cd_ids of the matching targets
92     * @throws Exception
93     */
94    private Collection<Integer> getSearchHits(String query) throws Exception {
95        return getFilteredSearchHits(query, null);
96    }
97
98    /**
99     * Warmup search to load structure cache.
00     */
01    private void warmupSearch() throws Exception {
02        System.out.println("Warmup search...");
03        getSearchHits("");
04    }
05
06    /**
07     * Get hits for a database search with filter ids.
08     * 
09     * @param query the query string
10     * @param cd_ids the ids to use as filter, search will be performed only on molecules with
11     *            these ids
12     * @return the cd_ids of the matching targets
13     * @throws Exception
14     */
15    private Collection<Integer> getFilteredSearchHits(String query,
16            Collection<Integer> filterIds) throws Exception {
17
18        // Create options and searcher
19        JChemSearchOptions searchOpts = new JChemSearchOptions(SearchConstants.SUBSTRUCTURE);
20        JChemSearch jcs = new JChemSearch();
21        jcs.setSearchOptions(searchOpts);
22        jcs.setConnectionHandler(connHandler);
23        jcs.setStructureTable(TABLE_NAME);
24        jcs.setQueryStructure(query);
25        if (filterIds != null) {
26            jcs.setFilterIDList(MultipleQueriesExample.toIntArray(filterIds));
27        }
28
29        // Perform search and create results
30        jcs.run();
31        int[] results = jcs.getResults();
32        return MultipleQueriesExample.toIntegerList(results);
33    }
34
35    private void listResults(Collection<Integer> results) {
36        System.out.printf("Result count: %d\n", results.size());
37        System.out.printf("Result cd_ids: %s\n", results.toString());
38        System.out.println();
39    }
40
41    /**
42     * Converts the given int array to an Integer list.
43     */
44    public static List<Integer> toIntegerList(int[] source) {
45        List<Integer> result = new ArrayList<Integer>(source.length);
46        for (int i : source) {
47            result.add(i);
48        }
49        return result;
50    }
51
52    /**
53     * Converts the given collection of Integer objects to int array.
54     */
55    public static int[] toIntArray(Collection<Integer> source) {
56        int[] result = new int[source.size()];
57        int i = 0;
58        for (Integer x : source) {
59            result[i++] = x;
60        }
61        return result;
62    }
63
64}
65