View Full Version : [Sql Server 2008 /C#/EF 4]Memorizzare files e ricerche full text
RaouL_BennetH
11-07-2011, 22:29
Buonasera a tutti :)
C'è qualcuno di voi che ha esperienza e che potrebbe suggerirmi qualcosa in merito a:
1) memorizzare files diversi su un db sql server (possono essere .doc, xls, pdf, email)
2) come funziona una ricerca di tipo full text sui documenti che verranno memorizzati sul db in un'apposita tabella ?
Il linguaggio e le tecnologie che devo usare sono C# ed Entity Framework.
Grazie mille a tutti :)
RaouL.
DioBrando
12-07-2011, 00:23
Buonasera a tutti :)
C'è qualcuno di voi che ha esperienza e che potrebbe suggerirmi qualcosa in merito a:
1) memorizzare files diversi su un db sql server (possono essere .doc, xls, pdf, email)
2) come funziona una ricerca di tipo full text sui documenti che verranno memorizzati sul db in un'apposita tabella ?
Il linguaggio e le tecnologie che devo usare sono C# ed Entity Framework.
Grazie mille a tutti :)
RaouL.
mai usato onestamente, però di materiale ne trovi parecchio.
Per esempio:
http://msdn.microsoft.com/en-us/vcsharp/Video/dd565857
Ma è un'applicazione...usi dei servizi, LINQ...?
RaouL_BennetH
12-07-2011, 22:18
mai usato onestamente, però di materiale ne trovi parecchio.
Per esempio:
http://msdn.microsoft.com/en-us/vcsharp/Video/dd565857
Ma è un'applicazione...usi dei servizi, LINQ...?
Ciao e grazie per la risposta ed il link segnalato :)
Per rispondere alla tua domanda:
Si, è un'applicazione. Si tratta di fare "in piccolo" una gestione documentale.
Io sono riuscito a fare in modo che qualsiasi documento venga memorizzato (memorizzo soltanto il path del documento), sia poi facilmente recuperabile mediante l'uso di tags preventivamente inseriti o di barcode (utilizzando itextsharp).
Ora dovrei fare in modo di creare un repository unico per qualsiasi tipo di documento: pdf, xls, immagini varie, email, etc... e mediante una ricerca, ad esempio: "pippo", mi trovi tutti i documenti che contengono tale termine.
Io, seguendo il modello dei veri programmi di gestione documentale, ho disegnato anche le varie classi documentali di appartenenza.
Ma questo tipo di ricerca mi è stato richiesto ed ho le idee alquanto confuse.
Grazie :)
RaouL.
DioBrando
13-07-2011, 00:13
Ciao e grazie per la risposta ed il link segnalato :)
Per rispondere alla tua domanda:
Si, è un'applicazione. Si tratta di fare "in piccolo" una gestione documentale.
Io sono riuscito a fare in modo che qualsiasi documento venga memorizzato (memorizzo soltanto il path del documento), sia poi facilmente recuperabile mediante l'uso di tags preventivamente inseriti o di barcode (utilizzando itextsharp).
Ora dovrei fare in modo di creare un repository unico per qualsiasi tipo di documento: pdf, xls, immagini varie, email, etc... e mediante una ricerca, ad esempio: "pippo", mi trovi tutti i documenti che contengono tale termine.
Io, seguendo il modello dei veri programmi di gestione documentale, ho disegnato anche le varie classi documentali di appartenenza.
Ma questo tipo di ricerca mi è stato richiesto ed ho le idee alquanto confuse.
Grazie :)
RaouL.
Prego, figurati :)
Come repository mi viene in mente DDD ed il repository pattern, con una separazione netta tra domain model e la parte di persistenza dei dati (la presentazione scegli tu come ti verrebbe meglio, se applicazione web, Winform ecc.).
Però se mi parli di gestione documentale pur non avendolo mai utilizzato sul lavoro, hai pensato all'adozione di Sharepoint eventualmente?
E' pensato proprio per quello scopo in fin dei conti :D
Reportistica ecc. ecc.
E puoi usare MVC...
RaouL_BennetH
13-07-2011, 08:25
Buondì :)
Per Sharepoint non ci è stata fatta menzione, credo quindi che, almeno in questa fase non sia per nulla previsto.
Altro piccolo problema, i nostri client sono tutti con Windows 7 64 Bit mentre la versione di Sql Server 2008 alla quale accediamo è una versione 32 bit e non può essere abilitato il nuovo meccanismo di gestione dei files FILESTREAM.
Pensavo quindi di fare una tabella così composta:
ID
FileName varchar
FileExtension varchar
FileContent - ?????
UploadDate datetime
Non ho idea di che tipo di dato usare per memorizzare il contenuto del file e dalle documentazioni che sto leggendo ognuno dice una cosa diversa:
varbinary, blob, image, etc..
Vabbè... diciamo che potrei "iniziare" con uno qualsiasi.
Mi resta comunque il buio totale su come effettuare una ricerca all'interno di essi; per spiegarmi meglio:
Supposto che l'utente che ha precedentemente ha memorizzato il file non si ricordi:
il nome del file
l'estensione
non ha assegnato nessun tag (questo tipo di funzione l'ho già implementata e funziona)
deve quindi fare una ricerca sul contenuto del file, ad esempio con: "banca Thief & Gangsta Inc" .
Vorrei ragionare solo lato DB e crearmi una stored (casomai cambia linguaggio e framework almeno ....) ma non ho idea di come fare appunto la ricerca all'interno dei contenuti .
RaouL.
RaouL_BennetH
13-07-2011, 08:47
mmm.. con questo link mi si è tolta almeno qualche nuvoletta nebbiosa:
http://www.simple-talk.com/sql/learn-sql-server/understanding-full-text-indexing-in-sql-server/
DioBrando
13-07-2011, 11:51
mmm.. con questo link mi si è tolta almeno qualche nuvoletta nebbiosa:
http://www.simple-talk.com/sql/learn-sql-server/understanding-full-text-indexing-in-sql-server/
Se devi cercare nel contenuto allora sì la soluzione migliore è usare l'FTS (FUll Text Search) di SQL Server che tra parentesi credo sia una funzionalità specifica proprio del DBMS Microsoft (magari è implementata anche su Oracle ma non ricordo come funziona :D ) e differente dal classico "like"
Il problema è l'interazione però con LINQ perché, a quanto ne so, non la supporta ancora.
Magari non ne avete bisogno (usando Entity Framework però mi viene difficile pensarlo dato che uno dei punti forti di quell'ORM è proprio il provider LINQ) ma ci sono comunque un paio di soluzioni "caserecce".
http://stackoverflow.com/questions/565617/full-text-search-in-linq
http://sqlblogcasts.com/blogs/simons/archive/2008/12/18/LINQ-to-SQL---Enabling-Fulltext-searching.aspx
RaouL_BennetH
18-07-2011, 22:52
Se devi cercare nel contenuto allora sì la soluzione migliore è usare l'FTS (FUll Text Search) di SQL Server che tra parentesi credo sia una funzionalità specifica proprio del DBMS Microsoft (magari è implementata anche su Oracle ma non ricordo come funziona :D ) e differente dal classico "like"
Il problema è l'interazione però con LINQ perché, a quanto ne so, non la supporta ancora.
Magari non ne avete bisogno (usando Entity Framework però mi viene difficile pensarlo dato che uno dei punti forti di quell'ORM è proprio il provider LINQ) ma ci sono comunque un paio di soluzioni "caserecce".
http://stackoverflow.com/questions/565617/full-text-search-in-linq
http://sqlblogcasts.com/blogs/simons/archive/2008/12/18/LINQ-to-SQL---Enabling-Fulltext-searching.aspx
Ho visto che non è integrato però ho pensato che potrei passargli una stored (a EF intendo.... )
DioBrando
18-07-2011, 23:02
Ho visto che non è integrato però ho pensato che potrei passargli una stored (a EF intendo.... )
mi pare sia una delle soluzioni prospettate nei link :)
Non so quale sia la qualità del port su .net ma prova comunque a dare un occhiata a Lucene. http://incubator.apache.org/lucene.net/
Noi lo usiamo con Java e abbiamo su un indice con milioni di documenti su un db mysql.
Kralizek
19-07-2011, 08:42
Non so quale sia la qualità del port su .net ma prova comunque a dare un occhiata a Lucene. http://incubator.apache.org/lucene.net/
Noi lo usiamo con Java e abbiamo su un indice con milioni di documenti su un db mysql.
il port é tecnicamente ineccepibile perché é fatto line-by-line.
anche se nella community di sviluppatori c'é stato molto disappunto su questa linea perché avrebbero preferito mantenere una compatibilitá dal punto di vista funzionale ma usare tutte le capacitá di .net.
in pratica lucene.net é scritto in .net 2.0... preistoria
RaouL_BennetH
19-07-2011, 09:39
Interessante lucene ! grazie per la segnalazione !
Ma che tipo di documenti posso gestire ?
Interessante lucene ! grazie per la segnalazione !
Ma che tipo di documenti posso gestire ?
Sostanzialmente puoi gestire qualsiasi cosa da cui sia possibile estrarre del testo.
RaouL_BennetH
19-07-2011, 17:37
Sostanzialmente puoi gestire qualsiasi cosa da cui sia possibile estrarre del testo.
Mmm... perdonatemi ma c'è qualcosa che ancora non mi torna...
Non riesco a trovare nulla con cui indicizzare documenti esistenti, tipo .doc, .xls, email, pdf etc..
In ogni tutorial vedo che i documenti sono creati da codice, inserendo descrizioni.
Avreste qualche esempio da linkare ?
Grazie a tutti :)
RaouL.
Mmm... perdonatemi ma c'è qualcosa che ancora non mi torna...
Non riesco a trovare nulla con cui indicizzare documenti esistenti, tipo .doc, .xls, email, pdf etc..
In ogni tutorial vedo che i documenti sono creati da codice, inserendo descrizioni.
Avreste qualche esempio da linkare ?
Grazie a tutti :)
RaouL.
No lucene non fa estrazione di testo. A quello ci devi pensare tu. Una volta che hai il testo da indicizzare puoi usare gli esempi che si trovano anche per la versione java e provare ad adattarli per .net.
Kralizek
21-07-2011, 08:06
il port é tecnicamente ineccepibile perché é fatto line-by-line.
anche se nella community di sviluppatori c'é stato molto disappunto su questa linea perché avrebbero preferito mantenere una compatibilitá dal punto di vista funzionale ma usare tutte le capacitá di .net.
in pratica lucene.net é scritto in .net 2.0... preistoria
mi correggo dicendo che lucene non supportava i generics, quindi allo stato attuale era come se fosse stato scritto in .net 1.x
ora c'é un nuovo team e stanno .net-ifizzando (tradotto da ".net-fy") inserendo il supporto ai generics.
figo... .net 2.0 nel 2011
http://codeclimber.net.nz/archive/2011/07/18/Lucene-net-is-back-on-track.aspx
RaouL_BennetH
22-07-2011, 10:53
No lucene non fa estrazione di testo. A quello ci devi pensare tu. Una volta che hai il testo da indicizzare puoi usare gli esempi che si trovano anche per la versione java e provare ad adattarli per .net.
Allora mi sa che è più semplice (dato anche il volume da gestire) utilizzare ciò che offre Sql Server 2008. In questo progetto purtroppo sono solo :( e i tempi desiderati dai mega direttori galattici sono di pronta consegna per "ieri". Io investirei volentieri del tempo per apprendere altro.
Dico questo anche perchè ho visto che non è affatto banale estrarre del testo da files di diversa natura (jpg, pdf, doc, xls, etc..)
Allora mi sa che è più semplice (dato anche il volume da gestire) utilizzare ciò che offre Sql Server 2008. In questo progetto purtroppo sono solo :( e i tempi desiderati dai mega direttori galattici sono di pronta consegna per "ieri". Io investirei volentieri del tempo per apprendere altro.
Dico questo anche perchè ho visto che non è affatto banale estrarre del testo da files di diversa natura (jpg, pdf, doc, xls, etc..)
L'estrazione del testo non credo tu possa saltarla. Non conosco sqlserver ma secondo me non basta caricare sul file nel db dentro ad un blob binario per riuscire a fare ricerche dentro ad esso.
RaouL_BennetH
22-07-2011, 11:34
L'estrazione del testo non credo tu possa saltarla. Non conosco sqlserver ma secondo me non basta caricare sul file nel db dentro ad un blob binario per riuscire a fare ricerche dentro ad esso.
Hai ragione :)
Al momento ho individuato questa strategia:
1) Qualsiasi tipo di file lo converto in .pdf
2) Mediante PDFBox estraggo il testo
3) Il testo estratto lo do in pasto a lucene (e questo mi svincolerebbe anche
dall'utilizzo di un database)
Può andare ?
grazie :)
RaouL.
Hai ragione :)
Al momento ho individuato questa strategia:
1) Qualsiasi tipo di file lo converto in .pdf
2) Mediante PDFBox estraggo il testo
3) Il testo estratto lo do in pasto a lucene (e questo mi svincolerebbe anche
dall'utilizzo di un database)
Può andare ?
grazie :)
RaouL.
Se riesci ad automatizzare il tutto non dovrebbero esserci problemi. Al posto di pdfbox io però userei itextsharp per l'estrazione del testo dai pdf.
DioBrando
22-07-2011, 15:45
Se riesci ad automatizzare il tutto non dovrebbero esserci problemi. Al posto di pdfbox io però userei itextsharp per l'estrazione del testo dai pdf.
occhio che itextSharp è diventato a pagamento con la 5.
Devi cercare la 4.x e non è così semplice (io ci sono riuscito ma ho dovuto lurkare non poco...se serve ti posso passare il sorgente e dll).
RaouL_BennetH
22-07-2011, 16:23
Se riesci ad automatizzare il tutto non dovrebbero esserci problemi. Al posto di pdfbox io però userei itextsharp per l'estrazione del testo dai pdf.
Il fatto è che PDFBox ha una funzione integrata (che ancora non ho capito come usare) per indicizzare direttamente dei pdf in lucene.
La classe che mette a disposizione è:
LucenePDFDocument
Ho trovato però esempi solo in Java che mi sono difficili da "tradurre".
Al momento però, non ho approfondito (lato .Net)
Ciò che sono riuscito a fare, giusto per dei test è:
Directory directory = FSDirectory.Open(new DirectoryInfo(Environment.CurrentDirectory + "@IndexDirectory"));
//metodo di test per l'estrazione di testo da PDF
private string ExtractTextFromPDF(string fileName)
{
PDDocument myPdf = PDDocument.load(fileName);
PDFTextStripper extractor = new PDFTextStripper();
return extractor.getText(myPdf);
}
private void AddDocToRepository()
{
string fileContents = ExtractTextFromPDF(@"prova.pdf");
Analyzer a = new StandardAnalyzer(Version.LUCENE_29); //lucene dll ver 2.9.2
Document docToIndex = new Document();
docToIndex.Add(new Field("Contenuti", fileContents, Field.Store.YES, Field.Index.ANALYZED));
IndexWriter iWriter = new IndexWriter(directory, a, true, IndexWriter.MaxFieldLength.UNLIMITED);
iWriter.AddDocument(docToIndex);
iWriter.Optimize();
iWriter.Close();
}
//from some click in teh code
private void BtnTest_Click(object sender, EventArgs e)
{
AddDocToRepository();
}
Ho eseguito il tutto, e riscontro che:
Una directory di nome IndexDirectory mi viene correttamente creata.
All'interno trovo i seguenti files:
_0.cfs
_0.cfx
segments.gen
segments_2
Sempre seguendo alcune guide ho provato ad implementare un rudimentale metodo di ricerca:
private int TestingFullTextSearchOnIndexedDocs()
{
Analyzer a = new StandardAnalyzer(Version.LUCENE_29);
IndexReader iReader = IndexReader.Open(directory, true);
Searcher iSearch = new IndexSearcher(iReader);
var parser = new QueryParser(Version.LUCENE_29, "Contenuti", a);
var query = parser.Parse("asd lol wtf rofl");
TopDocs results = iSearch.Search(query, iReader.MaxDoc());
return results.totalHits;
}
Per qualsiasi parola contenuta nel documento, mi restituisce correttamente "1", considerando che ho soltanto un documento nella index.
RaouL_BennetH
22-07-2011, 21:58
Ho solo un piccolo grattacapo con i test di sopra....
Ogni volta che cerco di aggiungere un documento, mi cancella i vecchi...
banryu79
23-07-2011, 09:18
Ho solo un piccolo grattacapo con i test di sopra....
Ogni volta che cerco di aggiungere un documento, mi cancella i vecchi...
Probabilmente IndexWriter va a sovvrascrivere i file già contenuti nella directory indicata. Forse devi ogni volta creare una nuova directory, per ogni nuovo documento, per memorizzarne i 4 files generati?
_0.cfs
_0.cfx
segments.gen
segments_2
Controlla bene la documentazione.
Il terzo parametro di IndexWriter dice a Lucene se creare un nuovo indice o aggiungere a quello esistente! Devi metterlo a false.
RaouL_BennetH
23-07-2011, 10:19
Il terzo parametro di IndexWriter dice a Lucene se creare un nuovo indice o aggiungere a quello esistente! Devi metterlo a false.
E' vero solo per la prima esecuzione, quando mi deve creare la directory da indicizzare.
Nel codice ho cambiato a false ma il risultato non cambia.
RaouL_BennetH
23-07-2011, 10:32
per meglio dire:
private void AddDocumentToIndex(DocumIndex docToIndex)
{
bool indexExist;
CheckIndexDirectory(out indexExist, IndexPath());
if (indexExist)
{
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_29);
var indexWriter = new IndexWriter(IndexDirectory(), analyzer, false, IndexWriter.MaxFieldLength.UNLIMITED);
Document doc = new Document();
doc.Add(new Field("ID", docToIndex.ID, Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.Add(new Field("File", docToIndex.DocumentName, Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.Add(new Field("Contents", docToIndex.DocumentContent, Field.Store.YES, Field.Index.ANALYZED));
indexWriter.AddDocument(doc);
indexWriter.Optimize();
indexWriter.Close();
}
}
RaouL_BennetH
23-07-2011, 11:40
mmm... mi sta venendo il dubbio che ci debba essere soltanto un "file" che contiene tutto. Qualcuno può confermare ?
RaouL_BennetH
24-07-2011, 17:48
Sono tornato sulla via 'principale' :) ovvero gestisco mediante sql server (che comunque per l'applicazione è necessario) il fts.
Come già detto sono solo nel progetto e non è la voglia che mi manca di studiare altre librerie, è proprio una questione di tempo :(
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.