You can build such solution with Lucene .Net.
Keep your docs in database (as already) and index with Lucene.Net docs you want.
Lucene will have its own index in file system.
You need to provide synchronization between your docs in DB and Lucene index, so when document in DB changes, you need to re-index it with Lucene.
Synchronization (matching between DB and Lucene index) can be based on some unique key value from DB (ex: ID).
So, when you want to add some document to Lucene index, you index the document content (you don't need to save content in Lucene) and 'save' it in Lucene with unique key value from DB (lets say ID).
Then you can search Lucene index and get list of matching document IDs.
And retreive them from your DB by those IDs and show to user.
Below is example method from my project, it adds document to Lucene index.
InformationAsset in method argument is the document from DB I want to index.
This method creates 'Lucene document' with few 'fields':
- 'field': content of the doc from db (InformationAsset from method argument)
- 'fieldId': it's ID of the InformationAsset from database, to match Database and Lucene index
- 'fieldPubDate': publication date, I can create advanced queries to Lucene engine basing on all fields.
'fieldDataSource': it's some kind of category.
public void AddToIndex(Entities.InformationAsset infAsset, IList<Keyword> additionalKeywords)
{
Analyzer analyzer = new StandardAnalyzer();
IndexWriter indexWriter = new IndexWriter(LuceneDir, analyzer, false);
Document doc = new Document();
// string z dodatkowymi slowami po ktorych ma byc tez zindeksowana tresc
string addKeysStr = "";
if(additionalKeywords != null)
{
foreach (Keyword keyword in additionalKeywords)
{
addKeysStr += " " + keyword.Value;
}
}
addKeysStr += " " + m_RootKeyword;
string contentStr;
contentStr = infAsset.Title + " " + infAsset.Content + addKeysStr;
// indeksacja pola z trescia
Field field = new Field(LuceneFieldName.Content, contentStr, Field.Store.NO, Field.Index.TOKENIZED,
Field.TermVector.YES);
// pole z Id
Field fieldId = new Field(LuceneFieldName.Id, infAsset.Id.ToString(), Field.Store.YES, Field.Index.UN_TOKENIZED);
// pole publish date
Field fieldPubDate = new Field(LuceneFieldName.PublishDate,
DateTools.DateToString(infAsset.PublishingDate, DateTools.Resolution.MINUTE),
Field.Store.YES, Field.Index.NO_NORMS, Field.TermVector.YES);
// pole DataSource
// pole z Id
Field fieldDataSource = new Field(LuceneFieldName.DataSourceId, infAsset.DataSource.Id.ToString(), Field.Store.YES,
Field.Index.UN_TOKENIZED);
doc.Add(field);
doc.Add(fieldId);
doc.Add(fieldPubDate);
doc.Add(fieldDataSource);
doc.SetBoost((float)CalculateDocBoostForInfAsset(infAsset));
indexWriter.AddDocument(doc);
indexWriter.Optimize();
indexWriter.Close();
}