我一直在阅读和搜索相当长的一段时间,似乎无法理解如何在包含jTable的Java程序中使用Lucene。
我希望能够做的是在提交新行条目时搜索表格。如果我在路径中包含3.3 Lucene jar文件,我是否只是从我的jTable创建一个TableModel并将其传递给TableSearcher构造函数?我已经包含了一些代码......拜托,我欢迎任何方向!谢谢。
这是我从存储在向量中的数据填充jTable的方法:
...
public static boolean hasSearchResults = false;
public String selectedRequirementName;
public TableSearcher ts;
DefaultTableModel sc;
public TablePanel(int z, String name, String reason) { //pulls in panel number, project name, and whether the project was new or opened, from the MainGUI class
initComponents();
sc=(DefaultTableModel) reqTable.getModel();
ts = new TableSearcher(sc);
aProject = new Project(reason, name); //calls Project class to control the project
try{
requirementsVector = new Vector(aProject.getRequirementsList());
requirementsList =new String[requirementsVector.size()];
for(int i=0; i < requirementsVector.size(); i++){
requirementsList[i] = requirementsVector.get(i).getName();
System.out.println(requirementsList[i]);
sc.addRow(new Object[]{
requirementsVector.get(i).getName(),
requirementsVector.get(i).getDefinition(),
requirementsVector.get(i).getType(),
requirementsVector.get(i).getPriority(),
requirementsVector.get(i).getAssigned(),
requirementsVector.get(i).getDue(),
requirementsVector.get(i).getStatus()});
//this.editingProjectName = name;
}
}catch(NullPointerException e1){
System.out.println(e1);
} ....
这是我的代码,它在jTable中插入一个新行:
private void ConfirmActionPerformed(java.awt.event.ActionEvent evt) {
String ReqName = nameTextField.getText();
String ReqDescription = descriptionTextField.getText();
String Type = (String)jType.getSelectedItem();
String Priority = (String)PriorityComboBox.getSelectedItem();
String Assigned = (String)jDateAssignedMonth.getSelectedItem() + "/" + (String)jDateAssignedDay.getSelectedItem() + "/" + (String)jDateAssignedYear.getSelectedItem();
String Due = (String)jDateDueMonth.getSelectedItem() + "/" + (String)jDateDueDay.getSelectedItem() + "/" + (String)jDateDueYear.getSelectedItem();
String Status = (String)jStatus.getSelectedItem();
// search string pass to TableSearcher
ts.search(ReqDescription);
if (editingaRow == false && !hasSearchResults){
sc.addRow(new Object[]{
ReqName,ReqDescription,Type,Priority,Assigned, Due, Status
});
requirementsVector.add(new Requirement(ReqName, ReqDescription, Type, Priority, Assigned, Due,Status));
aProject.saveRevision(requirementsVector, name);
}else if (editingaRow == true){
sc.setValueAt(ReqName,selectedRow,0);
sc.setValueAt(ReqDescription,selectedRow,1);
sc.setValueAt(Type,selectedRow,2);
sc.setValueAt(Priority,selectedRow,3);
sc.setValueAt(Assigned,selectedRow,4);
sc.setValueAt(Due,selectedRow,5);
sc.setValueAt(Status,selectedRow,6);
requirementsVector.setElementAt(new Requirement(ReqName, ReqDescription, Type, Priority, Assigned, Due,Status),(selectedRow));
aProject.saveRevision(requirementsVector, name);
editingaRow = false;
}
disableRequirementEditor();
newReq.setEnabled(true);
reqTable.clearSelection();
}
这是我正在使用的TableSearcher模型(我在搜索方法中添加了新功能)。发生的事情是当我输入一个新条目时,搜索会将该条目作为重复条目发现并在我在jqrame中将其返回给我在TableSearcher的搜索方法中实现。只有在索引表中没有匹配项的唯一条目才会发生这种情况。如果索引中的搜索结果与我的新条目匹配,则只有现有条目显示在我的jFrame中,而不是我正在尝试的新条目。
// provided by Jonathan Simon <jonathan_s_simon@yahoo.com>
class TableSearcher扩展了AbstractTableModel {
/**
* The inner table model we are decorating
*/
protected TableModel tableModel;
/**
* This listener is used to register this class as a listener to
* the decorated table model for update events
*/
private TableModelListener tableModelListener;
/**
* these keeps reference to the decorated table model for data
* only rows that match the search criteria are linked
*/
private ArrayList rowToModelIndex = new ArrayList();
//Lucene stuff.
/**
* In memory lucene index
*/
private RAMDirectory directory;
/**
* Cached lucene analyzer
*/
private Analyzer analyzer;
/**
* Links between this table model and the decorated table model
* are maintained through links based on row number. This is a
* key constant to denote "row number" for indexing
*/
private static final String ROW_NUMBER = "ROW_NUMBER";
/**
* Cache the current search String. Also used internally to
* key whether there is an active search running or not. i.e. if
* searchString is null, there is no active search.
*/
private String searchString = null;
/**
* @param tableModel The table model to decorate
*/
public TableSearcher(TableModel tableModel) {
analyzer = new WhitespaceAnalyzer();
tableModelListener = new TableModelHandler();
setTableModel(tableModel);
tableModel.addTableModelListener(tableModelListener);
clearSearchingState();
}
/**
*
* @return The inner table model this table model is decorating
*/
public TableModel getTableModel() {
return tableModel;
}
/**
* Set the table model used by this table model
* @param tableModel The new table model to decorate
*/
public final void setTableModel(TableModel tableModel) {
//remove listeners if there...
if (this.tableModel != null) {
this.tableModel.removeTableModelListener(tableModelListener);
}
this.tableModel = tableModel;
if (this.tableModel != null) {
this.tableModel.addTableModelListener(tableModelListener);
}
//recalculate the links between this table model and
//the inner table model since the decorated model just changed
reindex();
// let all listeners know the table has changed
fireTableStructureChanged();
}
/**
* Reset the search results and links to the decorated (inner) table
* model from this table model.
*/
private void reindex() {
try {
// recreate the RAMDirectory
directory = new RAMDirectory();
IndexWriter writer = new IndexWriter(directory, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED);
// iterate through all rows
for (int row=0; row < tableModel.getRowCount(); row++){
//for each row make a new document
Document document = new Document();
//add the row number of this row in the decorated table model
//this will allow us to retrive the results later
//and map this table model's row to a row in the decorated
//table model
document.add(new Field(ROW_NUMBER, "" + row, Field.Store.YES, Field.Index.ANALYZED));
//iterate through all columns
//index the value keyed by the column name
//NOTE: there could be a problem with using column names with spaces
for (int column=0; column < tableModel.getColumnCount(); column++){
String columnName = tableModel.getColumnName(column);
String columnValue = String.valueOf(tableModel.getValueAt(row, column)).toLowerCase();
document.add(new Field(columnName, columnValue, Field.Store.YES, Field.Index.ANALYZED));
}
writer.addDocument(document);
}
writer.optimize();
writer.close();
} catch (Exception e){
e.printStackTrace();
}
}
/**
* @return The current lucene analyzer
*/
public Analyzer getAnalyzer() {
return analyzer;
}
/**
* @param analyzer The new analyzer to use
*/
public void setAnalyzer(Analyzer analyzer) {
this.analyzer = analyzer;
//reindex from the model with the new analyzer
reindex();
//rerun the search if there is an active search
if (isSearching()){
search(searchString);
}
}
/**
* Run a new search.
*
* @param searchString Any valid lucene search string
*/
public void search(String searchString){
// to store row numbers of results rows to display later
Vector<String> rowNums = new Vector();
//if search string is null or empty, clear the search == search all
if (searchString == null || searchString.equals("")){
clearSearchingState();
fireTableDataChanged();
return;
}
try {
//cache search String
this.searchString = searchString;
//make a new index searcher with the in memory (RAM) index.
IndexSearcher is = new IndexSearcher(directory);
//make an array of fields - one for each column
String[] fields = new String[tableModel.getColumnCount()];
for (int t=0; t<tableModel.getColumnCount(); t++){
fields[t]=tableModel.getColumnName(t);
}
//build a query based on the fields, searchString and cached analyzer
//NOTE: This is an area for improvement since the MultiFieldQueryParser
// has some weirdness.
MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, analyzer);
Query query = parser.parse(searchString);
//run the search
Hits hits = is.search(query);
for (int t=0; t<hits.length(); t++){
Document document = hits.doc(t);
Fieldable field = document.getField(ROW_NUMBER);
// adding row numbers to vector
rowNums.add(field.stringValue());
}
// trying to display search results in new table
if(!rowNums.isEmpty()){
TablePanel.hasSearchResults = true;
for (int v=0; v<rowNums.size(); v++){
System.out.println("Match in row number " + rowNums.elementAt(v));
}
JFrame frame = new JFrame("Possible Duplicates");
String colNames[] = {"Name", "Definition", "Type", "Priority", "Date Assigned", "Due Date", "Status"};
DefaultTableModel dtm = new DefaultTableModel(null,colNames);
for (int r = 0; r<rowNums.size(); r++){
String ReqName = (String) tableModel.getValueAt(Integer.parseInt(rowNums.elementAt(r)), 0);
String ReqDescription = (String) tableModel.getValueAt(Integer.parseInt(rowNums.elementAt(r)), 1);
String Type = (String) tableModel.getValueAt(Integer.parseInt(rowNums.elementAt(r)), 2);
String Priority = (String) tableModel.getValueAt(Integer.parseInt(rowNums.elementAt(r)), 3);
String Assigned = (String) tableModel.getValueAt(Integer.parseInt(rowNums.elementAt(r)), 4);
String Due = (String) tableModel.getValueAt(Integer.parseInt(rowNums.elementAt(r)), 5);
String Status = (String) tableModel.getValueAt(Integer.parseInt(rowNums.elementAt(r)), 6);
dtm.addRow(new Object[]{
ReqName,ReqDescription,Type,Priority,Assigned, Due, Status
});
}
JTable tblResults = new JTable(dtm);
JScrollPane sp = new JScrollPane(tblResults);
JPanel panel = new JPanel(new BorderLayout());
panel.setPreferredSize(new Dimension(900,300));
panel.add(sp,BorderLayout.CENTER);
panel.add(new JLabel("Possible Duplicates",JLabel.CENTER),BorderLayout.SOUTH);
JOptionPane.showConfirmDialog(null,panel);
}
//reset this table model with the new results
resetSearchResults(hits);
} catch (Exception e){
e.printStackTrace();
}
//notify all listeners that the table has been changed
fireTableStructureChanged();
}
/**
*
* @param hits The new result set to set this table to.
*/
private void resetSearchResults(Hits hits) {
try {
//clear our index mapping this table model rows to
//the decorated inner table model
rowToModelIndex.clear();
//iterate through the hits
//get the row number stored at the index
//that number is the row number of the decorated
//tabble model row that we are mapping to
for (int t=0; t<hits.length(); t++){
Document document = hits.doc(t);
Fieldable field = document.getField(ROW_NUMBER);
rowToModelIndex.add(new Integer(field.stringValue()));
System.out.println("Something " + rowToModelIndex.add(new Integer(field.stringValue())));
clearSearchingState();
}
} catch (Exception e){
e.printStackTrace();
}
}
private int getModelRow(int row){
return ((Integer) rowToModelIndex.get(row)).intValue();
}
/**
* Clear the currently active search
* Resets the complete dataset of the decorated
* table model.
*/
private void clearSearchingState(){
searchString = null;
rowToModelIndex.clear();
for (int t=0; t<tableModel.getRowCount(); t++){
rowToModelIndex.add(new Integer(t));
}
}
// TableModel interface methods
public int getRowCount() {
return (tableModel == null) ? 0 : rowToModelIndex.size();
}
public int getColumnCount() {
return (tableModel == null) ? 0 : tableModel.getColumnCount();
}
public String getColumnName(int column) {
return tableModel.getColumnName(column);
}
public Class getColumnClass(int column) {
return tableModel.getColumnClass(column);
}
public boolean isCellEditable(int row, int column) {
return tableModel.isCellEditable(getModelRow(row), column);
}
public Object getValueAt(int row, int column) {
return tableModel.getValueAt(getModelRow(row), column);
}
public void setValueAt(Object aValue, int row, int column) {
tableModel.setValueAt(aValue, getModelRow(row), column);
}
private boolean isSearching() {
return searchString != null;
}
private class TableModelHandler implements TableModelListener {
public void tableChanged(TableModelEvent e) {
// If we're not searching, just pass the event along.
if (!isSearching()) {
clearSearchingState();
reindex();
fireTableChanged(e);
return;
}
// Something has happened to the data that may have invalidated the search.
reindex();
search(searchString);
fireTableDataChanged();
return;
}
}
答案 0 :(得分:0)
看起来您的代码没有使用Lucene索引表数据。一种简单的方法是创建自己的内部索引表模型,使用可以连接的公开搜索功能来限制显示的数据。这就是我几年前在Swing Hacks中所写的内容。
没有索引,Lucene不会自动“工作”,因为它在你的类路径中。
Jonathan
答案 1 :(得分:0)
在你的情况下,你会做这样的事情来创建文档,它将被保存在索引中。
此代码不完整或无错误;但更多的是让你前进的起点
Document doc = new Document();
doc.add(new Field("ReqName", ReqName, Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("ReqDescription", ReqDescription, Field.Store.YES, Field.Index.ANALYZED));
doc.add(new Field("Type", Type, Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("Priority", Priority, Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("Assigned", Assigned, Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("Due", Due, Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("Status", Status, Field.Store.YES, Field.Index.NOT_ANALYZED));
writer.addDocument(doc);
writer.close();