Skip to content
This repository was archived by the owner on May 26, 2026. It is now read-only.

Commit 85216aa

Browse files
committed
Removed dependency on Lucene. Restricted blocking keys to lowercase.
1 parent ff37d72 commit 85216aa

138 files changed

Lines changed: 218 additions & 449 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

jedai-core/pom.xml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -73,20 +73,6 @@
7373
<version>3.1.0</version>
7474
</dependency>
7575

76-
<!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-core -->
77-
<dependency>
78-
<groupId>org.apache.lucene</groupId>
79-
<artifactId>lucene-core</artifactId>
80-
<version>6.0.1</version>
81-
</dependency>
82-
83-
<!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-analyzers-common -->
84-
<dependency>
85-
<groupId>org.apache.lucene</groupId>
86-
<artifactId>lucene-analyzers-common</artifactId>
87-
<version>6.0.1</version>
88-
</dependency>
89-
9076
<!-- https://mvnrepository.com/artifact/com.opencsv/opencsv -->
9177
<dependency>
9278
<groupId>com.opencsv</groupId>
Lines changed: 69 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
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+
*/
1716
package BlockBuilding;
1817

1918
import DataModel.AbstractBlock;
@@ -22,34 +21,15 @@
2221
import DataModel.EntityProfile;
2322
import DataModel.UnilateralBlock;
2423
import Utilities.Converter;
25-
import java.io.IOException;
24+
2625
import java.util.ArrayList;
2726
import java.util.HashMap;
2827
import java.util.List;
2928
import java.util.Map;
29+
import java.util.Map.Entry;
3030
import java.util.Set;
3131
import java.util.logging.Level;
3232
import 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

Comments
 (0)