11/*
2- * Copyright [2016] [George Papadakis (gpapadis@yahoo.gr)]
3- *
4- * Licensed under the Apache License, Version 2.0 (the "License");
5- * you may not use this file except in compliance with the License.
6- * You may obtain a copy of the License at
7- *
8- * http://www.apache.org/licenses/LICENSE-2.0
9- *
10- * Unless required by applicable law or agreed to in writing, software
11- * distributed under the License is distributed on an "AS IS" BASIS,
12- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13- * See the License for the specific language governing permissions and
14- * limitations under the License.
15- */
16-
2+ * Copyright [2016] [George Papadakis (gpapadis@yahoo.gr)]
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
1716package BlockBuilding ;
1817
1918import DataModel .AbstractBlock ;
2221import DataModel .EntityProfile ;
2322import DataModel .UnilateralBlock ;
2423import Utilities .Converter ;
25- import java . io . IOException ;
24+
2625import java .util .ArrayList ;
2726import java .util .HashMap ;
2827import java .util .List ;
2928import java .util .Map ;
29+ import java .util .Map .Entry ;
3030import java .util .Set ;
3131import java .util .logging .Level ;
3232import java .util .logging .Logger ;
33- import org .apache .lucene .analysis .Analyzer ;
34- import org .apache .lucene .analysis .core .SimpleAnalyzer ;
35- import org .apache .lucene .document .Document ;
36- import org .apache .lucene .document .Field ;
37- import org .apache .lucene .document .StoredField ;
38- import org .apache .lucene .document .StringField ;
39- import org .apache .lucene .index .DirectoryReader ;
40- import org .apache .lucene .index .Fields ;
41- import org .apache .lucene .index .IndexReader ;
42- import org .apache .lucene .index .IndexWriter ;
43- import org .apache .lucene .index .IndexWriterConfig ;
44- import org .apache .lucene .index .MultiFields ;
45- import org .apache .lucene .index .PostingsEnum ;
46- import org .apache .lucene .index .Term ;
47- import org .apache .lucene .index .Terms ;
48- import org .apache .lucene .index .TermsEnum ;
49- import org .apache .lucene .search .DocIdSetIterator ;
50- import org .apache .lucene .store .Directory ;
51- import org .apache .lucene .store .RAMDirectory ;
52- import org .apache .lucene .util .BytesRef ;
5333
5434/**
5535 *
@@ -63,10 +43,10 @@ public abstract class AbstractBlockBuilding implements IBlockBuilding {
6343 protected double noOfEntitiesD2 ;
6444
6545 protected final List <AbstractBlock > blocks ;
66- protected Directory indexDirectoryD1 ;
67- protected Directory indexDirectoryD2 ;
6846 protected List <EntityProfile > entityProfilesD1 ;
6947 protected List <EntityProfile > entityProfilesD2 ;
48+ protected Map <String , List <Integer >> invertedIndexD1 ;
49+ protected Map <String , List <Integer >> invertedIndexD2 ;
7050
7151 public AbstractBlockBuilding () {
7252 blocks = new ArrayList <>();
@@ -75,32 +55,10 @@ public AbstractBlockBuilding() {
7555 }
7656
7757 protected void buildBlocks () {
78- setMemoryDirectory ( );
58+ indexEntities ( invertedIndexD1 , entityProfilesD1 );
7959
80- IndexWriter iWriter1 = openWriter (indexDirectoryD1 );
81- indexEntities (iWriter1 , entityProfilesD1 );
82- closeWriter (iWriter1 );
83-
84- if (indexDirectoryD2 != null ) {
85- IndexWriter iWriter2 = openWriter (indexDirectoryD2 );
86- indexEntities (iWriter2 , entityProfilesD2 );
87- closeWriter (iWriter2 );
88- }
89- }
90-
91- protected void closeReader (IndexReader iReader ) {
92- try {
93- iReader .close ();
94- } catch (IOException ex ) {
95- LOGGER .log (Level .SEVERE , null , ex );
96- }
97- }
98-
99- protected void closeWriter (IndexWriter iWriter ) {
100- try {
101- iWriter .close ();
102- } catch (IOException ex ) {
103- LOGGER .log (Level .SEVERE , null , ex );
60+ if (invertedIndexD2 != null ) {
61+ indexEntities (invertedIndexD2 , entityProfilesD2 );
10462 }
10563 }
10664
@@ -110,7 +68,7 @@ protected void closeWriter(IndexWriter iWriter) {
11068 public List <AbstractBlock > getBlocks (List <EntityProfile > profiles ) {
11169 return this .getBlocks (profiles , null );
11270 }
113-
71+
11472 @ Override
11573 public List <AbstractBlock > getBlocks (List <EntityProfile > profilesD1 ,
11674 List <EntityProfile > profilesD2 ) {
@@ -120,9 +78,11 @@ public List<AbstractBlock> getBlocks(List<EntityProfile> profilesD1,
12078 return null ;
12179 }
12280
81+ invertedIndexD1 = new HashMap <>();
12382 entityProfilesD1 = profilesD1 ;
12483 noOfEntitiesD1 = entityProfilesD1 .size ();
12584 if (profilesD2 != null ) {
85+ invertedIndexD2 = new HashMap <>();
12686 entityProfilesD2 = profilesD2 ;
12787 noOfEntitiesD2 = entityProfilesD2 .size ();
12888 }
@@ -138,179 +98,79 @@ public double getBruteForceComparisons() {
13898 return noOfEntitiesD1 * noOfEntitiesD2 ;
13999 }
140100
141- protected int [] getDocumentIds (IndexReader reader ) {
142- int [] documentIds = new int [reader .numDocs ()];
143- for (int i = 0 ; i < documentIds .length ; i ++) {
144- try {
145- Document document = reader .document (i );
146- documentIds [i ] = Integer .parseInt (document .get (DOC_ID ));
147- } catch (IOException ex ) {
148- LOGGER .log (Level .SEVERE , null , ex );
149- }
150- }
151- return documentIds ;
152- }
153-
154101 public double getTotalNoOfEntities () {
155102 if (entityProfilesD2 == null ) {
156103 return noOfEntitiesD1 ;
157104 }
158105 return noOfEntitiesD1 + noOfEntitiesD2 ;
159106 }
160107
161- protected void indexEntities (IndexWriter index , List <EntityProfile > entities ) {
162- try {
163- int counter = 0 ;
164- for (EntityProfile profile : entities ) {
165- Document doc = new Document ();
166- doc .add (new StoredField (DOC_ID , counter ++));
167- for (Attribute attribute : profile .getAttributes ()) {
168- getBlockingKeys (attribute .getValue ()).stream ().filter ((key ) -> (0 < key .trim ().length ())).forEach ((key ) -> {
169- doc .add (new StringField (VALUE_LABEL , key .trim (), Field .Store .YES ));
170- });
108+ protected void indexEntities (Map <String , List <Integer >> index , List <EntityProfile > entities ) {
109+ int counter = 0 ;
110+ for (EntityProfile profile : entities ) {
111+ for (Attribute attribute : profile .getAttributes ()) {
112+ Set <String > keys = getBlockingKeys (attribute .getValue ());
113+ for (String key : keys ) {
114+ String normalizedKey = key .trim ().toLowerCase ();
115+ if (0 < normalizedKey .length ()) {
116+ List <Integer > entityList = index .get (normalizedKey );
117+ if (entityList == null ) {
118+ entityList = new ArrayList <>();
119+ index .put (normalizedKey , entityList );
120+ }
121+ entityList .add (counter );
122+ }
171123 }
172- index .addDocument (doc );
173124 }
174- } catch (IOException ex ) {
175- LOGGER .log (Level .SEVERE , null , ex );
125+ counter ++;
176126 }
177127 }
178128
179- public static IndexReader openReader (Directory directory ) {
180- try {
181- return DirectoryReader .open (directory );
182- } catch (IOException ex ) {
183- LOGGER .log (Level .SEVERE , null , ex );
184- return null ;
185- }
186- }
187-
188- protected IndexWriter openWriter (Directory directory ) {
189- try {
190- Analyzer analyzer = new SimpleAnalyzer ();
191- IndexWriterConfig config = new IndexWriterConfig (analyzer );
192- return new IndexWriter (directory , config );
193- } catch (IOException ex ) {
194- LOGGER .log (Level .SEVERE , null , ex );
195- return null ;
196- }
197- }
198-
199- protected Map <String , int []> parseD1Index (IndexReader d1Index , IndexReader d2Index ) {
200- try {
201- int [] documentIds = getDocumentIds (d1Index );
202- final Map <String , int []> hashedBlocks = new HashMap <>();
203- Fields fields = MultiFields .getFields (d1Index );
204- for (String field : fields ) {
205- Terms terms = fields .terms (field );
206- TermsEnum termsEnum = terms .iterator ();
207- BytesRef text ;
208- while ((text = termsEnum .next ()) != null ) {
209- // check whether it is a common term
210- int d2DocFrequency = d2Index .docFreq (new Term (field , text ));
211- if (d2DocFrequency == 0 ) {
212- continue ;
213- }
214-
215- final List <Integer > entityIds = new ArrayList <>();
216- PostingsEnum pe = MultiFields .getTermDocsEnum (d1Index , field , text );
217- int doc ;
218- while ((doc = pe .nextDoc ()) != DocIdSetIterator .NO_MORE_DOCS ) {
219- entityIds .add (documentIds [doc ]);
220- }
221-
222- int [] idsArray = Converter .convertCollectionToArray (entityIds );
223- hashedBlocks .put (text .utf8ToString (), idsArray );
224- }
129+ protected Map <String , int []> parseD1Index () {
130+ final Map <String , int []> hashedBlocks = new HashMap <>();
131+ for (Entry <String , List <Integer >> entry : invertedIndexD1 .entrySet ()) {
132+ // check whether it is a common term
133+ if (!invertedIndexD2 .containsKey (entry .getKey ())) {
134+ continue ;
225135 }
226- return hashedBlocks ;
227- } catch (IOException ex ) {
228- LOGGER .log (Level .SEVERE , null , ex );
229- return null ;
136+
137+ int [] idsArray = Converter .convertCollectionToArray (entry .getValue ());
138+ hashedBlocks .put (entry .getKey (), idsArray );
230139 }
140+ return hashedBlocks ;
231141 }
232142
233- protected void parseD2Index (IndexReader d2Index , Map <String , int []> hashedBlocks ) {
234- try {
235- int [] documentIds = getDocumentIds (d2Index );
236- Fields fields = MultiFields .getFields (d2Index );
237- for (String field : fields ) {
238- Terms terms = fields .terms (field );
239- TermsEnum termsEnum = terms .iterator ();
240- BytesRef text ;
241- while ((text = termsEnum .next ()) != null ) {
242- if (!hashedBlocks .containsKey (text .utf8ToString ())) {
243- continue ;
244- }
245-
246- final List <Integer > entityIds = new ArrayList <>();
247- PostingsEnum pe = MultiFields .getTermDocsEnum (d2Index , field , text );
248- int doc ;
249- while ((doc = pe .nextDoc ()) != DocIdSetIterator .NO_MORE_DOCS ) {
250- entityIds .add (documentIds [doc ]);
251- }
252-
253- int [] idsArray = Converter .convertCollectionToArray (entityIds );
254- int [] d1Entities = hashedBlocks .get (text .utf8ToString ());
255- blocks .add (new BilateralBlock (d1Entities , idsArray ));
256- }
143+ protected void parseD2Index (Map <String , int []> hashedBlocks ) {
144+ for (Entry <String , List <Integer >> entry : invertedIndexD2 .entrySet ()) {
145+ if (!hashedBlocks .containsKey (entry .getKey ())) {
146+ continue ;
257147 }
258148
259- } catch (IOException ex ) {
260- LOGGER .log (Level .SEVERE , null , ex );
149+ int [] idsArray = Converter .convertCollectionToArray (entry .getValue ());
150+ int [] d1Entities = hashedBlocks .get (entry .getKey ());
151+ blocks .add (new BilateralBlock (d1Entities , idsArray ));
261152 }
262153 }
263154
264- protected void parseIndex (IndexReader d1Index ) {
265- try {
266- int [] documentIds = getDocumentIds (d1Index );
267- Fields fields = MultiFields .getFields (d1Index );
268- for (String field : fields ) {
269- Terms terms = fields .terms (field );
270- TermsEnum termsEnum = terms .iterator ();
271- BytesRef text ;
272- while ((text = termsEnum .next ()) != null ) {
273- if (termsEnum .docFreq () < 2 ) {
274- continue ;
275- }
276-
277- final List <Integer > entityIds = new ArrayList <>();
278- PostingsEnum pe = MultiFields .getTermDocsEnum (d1Index , field , text );
279- int doc ;
280- while ((doc = pe .nextDoc ()) != DocIdSetIterator .NO_MORE_DOCS ) {
281- entityIds .add (documentIds [doc ]);
282- }
283-
284- int [] idsArray = Converter .convertCollectionToArray (entityIds );
285- UnilateralBlock block = new UnilateralBlock (idsArray );
286- blocks .add (block );
287- }
155+ protected void parseIndex () {
156+ for (List <Integer > entityList : invertedIndexD1 .values ()) {
157+ if (1 < entityList .size ()) {
158+ int [] idsArray = Converter .convertCollectionToArray (entityList );
159+ UnilateralBlock block = new UnilateralBlock (idsArray );
160+ blocks .add (block );
288161 }
289- } catch (IOException ex ) {
290- LOGGER .log (Level .SEVERE , null , ex );
291162 }
292163 }
293-
164+
294165 //read blocks from Lucene index
295166 public List <AbstractBlock > readBlocks () {
296- IndexReader iReaderD1 = openReader (indexDirectoryD1 );
297167 if (entityProfilesD2 == null ) { //Dirty ER
298- parseIndex (iReaderD1 );
168+ parseIndex ();
299169 } else {
300- IndexReader iReaderD2 = openReader (indexDirectoryD2 );
301- Map <String , int []> hashedBlocks = parseD1Index (iReaderD1 , iReaderD2 );
302- parseD2Index (iReaderD2 , hashedBlocks );
303- closeReader (iReaderD2 );
170+ Map <String , int []> hashedBlocks = parseD1Index ();
171+ parseD2Index (hashedBlocks );
304172 }
305- closeReader (iReaderD1 );
306-
307- return blocks ;
308- }
309173
310- protected void setMemoryDirectory () {
311- indexDirectoryD1 = new RAMDirectory ();
312- if (entityProfilesD2 != null ) {
313- indexDirectoryD2 = new RAMDirectory ();
314- }
174+ return blocks ;
315175 }
316- }
176+ }
0 commit comments