0
votes

I have a set of data: ID, Name and a ArrayList associated with the ID. I wanted this data to be stored in the Lucene document. The search will be based on the Id and name. The List should not be indexed.

I do not know how a List/ArrayList can be stored in the Lucene Document. What is best way of doing this?

Apache Lucene verison I am using is 7.1.0.

Thanks.

Document doc = new Document();
String id = "something";
String name = "someName";
List someList = new ArrayList();
doc.add(new StringField("Id", id, Field.Store.YES));
doc.add(new TextField("name", name, Field.Store.YES));

How do I do something similar for the 'someList'?

1

1 Answers

0
votes

You can use StoredField.

A simple aproach might be serializing the list. Here is a sample code:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Random;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

public class LuceneTest {

    public static byte[] serialize(Object obj) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream(200000);
        ObjectOutputStream os = new ObjectOutputStream(bos);
        os.writeObject(obj);
        os.close();
        return bos.toByteArray();
    }

    public static Object unserialize(byte[] bytes) throws ClassNotFoundException, IOException {
        ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(bytes));
        Object result = is.readObject();
        is.close();
        return result;
    }

    public static void index() {
        String indexPath = "index";
        try {
            System.out.println("Indexing to directory '" + indexPath + "'...");
            Directory dir = FSDirectory.open(Paths.get(indexPath));
            Analyzer analyzer = new StandardAnalyzer();
            IndexWriterConfig iwc = new IndexWriterConfig(analyzer);

            iwc.setOpenMode(OpenMode.CREATE);

            IndexWriter writer = new IndexWriter(dir, iwc);

            for (int i = 0; i < 100; i++) {
                Document doc = new Document();
                String id = "id" + i;
                String name = "jack " + i;
                ArrayList<Object> someList = new ArrayList<>();
                someList.add(id + " => " + name);
                someList.add("index" + i);

                doc.add(new StringField("Id", id, Field.Store.YES));
                doc.add(new TextField("name", name, Field.Store.YES));
                doc.add(new StoredField("list", serialize(someList)));
                writer.addDocument(doc);
            }

            writer.close();
        } catch (IOException e) {
            System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage());
        }
    }

    public static void search() {
        String index = "index";
        String field = "name";
        int hitsPerPage = 10;
        try {
            IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(index)));
            IndexSearcher searcher = new IndexSearcher(reader);
            Analyzer analyzer = new StandardAnalyzer();

            QueryParser parser = new QueryParser(field, analyzer);

            Random rnd = new Random();
            for (int i = 0; i < 10; i++) {
                int randIndex = rnd.nextInt(100);

                String nameQuery = "" + randIndex;
                Query query = parser.parse(nameQuery);
                System.out.println("Searching for: " + query.toString(field));

                TopDocs results = searcher.search(query, hitsPerPage);
                ScoreDoc[] hits = results.scoreDocs;

                for (ScoreDoc scoreDoc : hits) {
                    Document doc = searcher.doc(scoreDoc.doc);
                    String id = doc.get("Id");
                    String name = doc.get("name");
                    ArrayList<Object> list = (ArrayList<Object>) unserialize(doc.getBinaryValue("list").bytes);
                    System.out.println("id: " + id + " name: " + name + " list: " + list);
                }
                System.out.println();
            }
            reader.close();
        } catch (Exception e) {
            System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage());
        }
    }

    public static void main(String[] args) {
        index();
        search();
    }
}