Lucene.Net: Searching multiple date/date-range in same document - lucene.net

I have an event which happens on multiple dates (like every 5th of month for the next 6 months). If a user searches for events for next 45 days on 4th than he should get above event, but for queries like next 7 days on 6th should not return above event.
I have create document for event and added multiple date filed on same document.
var event1 = new Document();
event1.Add(new Field("Id", "2", Field.Store.YES, Field.Index.NOT_ANALYZED));
event1.Add(new Field("Name", "Ford", Field.Store.YES, Field.Index.ANALYZED));
event1.Add(new Field("Desc", "Focus", Field.Store.YES, Field.Index.ANALYZED));
event1.Add(new NumericField("Date", (int)new DateTime(2012, 6, 05).Subtract(dt).TotalMinutes, Field.Store.YES, true));
event1.Add(new NumericField("Date", (int)new DateTime(2012, 7, 05).Subtract(dt).TotalMinutes, Field.Store.YES, true));
event1.Add(new NumericField("Date", (int)new DateTime(2012, 8, 05).Subtract(dt).TotalMinutes, Field.Store.YES, true));
The idea is that if I search on a specific date or date-range it should work. But once I try to write this document, it throws an NullReferenceException.
Directory directory = FSDirectory.Open(new DirectoryInfo(Environment.CurrentDirectory + "\\LuceneIndex"));
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_29);
var writer = new IndexWriter(directory, true, analyzer, true);
writer.AddDocument(event1);
I am not sure how to perform these type of searches.
Update 1:
writer.AddDocument(event1); causing the null reference,
Update 2:
at Lucene.Net.Store.IndexOutput.WriteString(String s)
at Lucene.Net.Index.FieldsWriter.WriteField(FieldInfo fi, Fieldable field)
at Lucene.Net.Index.StoredFieldsWriterPerThread.AddField(Fieldable field, FieldInfo fieldInfo)
at Lucene.Net.Index.DocFieldProcessorPerThread.ProcessDocument()
at Lucene.Net.Index.DocumentsWriter.UpdateDocument(Document doc, Analyzer analyzer, Term delTerm)
at Lucene.Net.Index.DocumentsWriter.AddDocument(Document doc, Analyzer analyzer)
at Lucene.Net.Index.IndexWriter.AddDocument(Document doc, Analyzer analyzer)
at Lucene.Net.Index.IndexWriter.AddDocument(Document doc)
at luceneSearch.Program.Main(String[] args) in

The NumericField constructor accepts a precisionStep, not the actual value. The correct usage requires you to call SetIntValue (or any of the other set*Value methods).
event1.Add(new NumericField("Date", Field.Store.YES, true)
.SetIntValue((int)new DateTime(2012, 6, 05).Subtract(dt).TotalMinutes));
event1.Add(new NumericField("Date", Field.Store.YES, true)
.SetIntValue((int)new DateTime(2012, 7, 05).Subtract(dt).TotalMinutes));
event1.Add(new NumericField("Date", Field.Store.YES, true)
.SetIntValue((int)new DateTime(2012, 8, 05).Subtract(dt).TotalMinutes));
The exception occurs because NumericField.StringValue() returns null if no value is set.

Related

How to get certain range of item from dart Map?

I have asked similar question before, but there's still something i think about. To begin with, i have an event Map like this:
final Map<DateTime, List<CleanCalendarEvent>>? events;
It mapped all my event based on event Date. I want to select some events in certain range of date. I know how to select all the events in one selected date, and put it in a List.
_selectedEventsList = widget.events?[DateTime(_selectedDate.year, _selectedDate.month, _selectedDate.day)] ??[];
The _selectedEventsList is a list of object named CleanCalendarEvent
List<CleanCalendarEvent>? _selectedEvents;
Note, my app look like this:
the lines below the date indicated how many event in one day. I want to get 10 nearest event. How can i do this? If it's a List, i can just get all items in the next 10 indexes, but how to do this in Map?
You can use compareTo() method to check whether specific DateTime is between the specified range.
The example below should help you to solve your problem.
void main() {
final events = <DateTime, List<String>>{
DateTime(2022, 11, 1): ['party'],
DateTime(2022, 11, 2): ['party', 'dance'],
DateTime(2022, 11, 3): ['party', 'gaming'],
DateTime(2022, 11, 4): ['nothing'],
DateTime(2022, 11, 5): ['dance'],
};
final selectedEvents = <String>[];
final startDate = DateTime(2022, 11, 2);
final endDate = DateTime(2022, 11, 4);
events.forEach((key, value) {
if (key.compareTo(startDate) >= 0 && key.compareTo(endDate) <= 0) {
selectedEvents.addAll(value);
}
});
print(selectedEvents);
}

How to filter a list of objects based on filer criteria in java?

I'm trying to filter the firstName,LastName and dateOfBirth according based on some regex expression using critera in mongodb.
Query query = new Query();
if(StringUtils.isNotBlank(firstName)) {
query.addCriteria(Criteria.where(ConstantsFIRST_NAME).
regex(".*" + firstName + ".*", "i"));
}
if(StringUtils.isNotBlank(lastName)) {
query.addCriteria(Criteria.where(Constants.LAST_NAME).
regex(".*" + lastName + ".*", "i"));
}
if(StringUtils.isNotBlank(dateOfBirth)) {
query.addCriteria(Criteria.where(Constants.DATE_OF_BIRTH).
regex(".*" + dateOfBirth + ".*", "i");
}
return mongoTemplate.find(query)
How to replicate the same in java8 using streams and filters when trying to iterate over a list of objects ?
List<Person> persons = new ArrayList<>();
persons.add(new Person("first1", "last1","dob1"));
persons.add(new Person(null, "last2","dob2"));
persons.add(new Person("first1", null, null));
persons.add(new Person("first2", "last2", "dob2"));
persons.add(new Person("first3", "last3", "dob3"));
persons.add(new Person(null, null), null);
persons.add(null);
For lists (and other collections), you can use .stream() to turn the collection in a stream. Then, you can use .filter() to execute certain filters on them. Afterwards, you can use the method .collect() to transform the remaining entries to another collection (you can e.g. collect them as a list again).
The method .filter() requires a Predicate which can be a simple lambda or a method reference. This predicate has to be true for all entries of the stream (the initial list) which should pass the filter.
Lets assume you have a List<Person> and every person has a name and an age. You want to get only the people with age 21 and older. The result should again be stored as a list.
List<Person> persons = new ArrayList<>();
persons.add(new Person("Karl", 14));
persons.add(new Person("Peter", 21));
persons.add(new Person("Susanne", 17));
persons.add(new Person("Kerstin", 30));
persons.add(new Person("Olli", 42));
persons.add(new Person("Josefine", 14));
List<Person> olderPeople = persons.stream().filter(p -> p.getAge() >= 21).collect(Collectors.toList());
You can also combine several filters. This can be achieved with the classical way of combining booleans with && or multiple sequential .filter(). You can of course argue about the efficiency of these two approaches. However, as this reply describes, this decision can be neglected.
You can have predicate combination like below:
public static Predicate<Person> getPersonPredicate(Person testPerson){
List<Predicate<Person>> predicates = new ArrayList<>();
predicates.add(Objects::nonNull);
predicates.add(p -> Objects.equals(p.getFirstName(), testPerson.getFirstName()));
predicates.add(p -> Objects.equals(p.getLastName(), testPerson.getLastName()));
//create single predicate with and conditions
return predicates.stream().reduce(p -> true, (personPredicate, other) -> personPredicate.and(other));
}

JPA IN-Parameter

I create a query like this in JPA (EclipseLink)
Query selectQuery = ... and SUBSTR(FOO, 0, 1) IN (?1)
or
Query selectQuery = ... and SUBSTR(FOO, 0, 1) IN ?1
I set a parameter like this:
selectQuery.setParameter(1, Arrays.asList(new String[] { "T" }));
However it is telling me
invalid column type
When I change my query to this:
Query selectQuery = ... and SUBSTR(FOO, 0, 1) IN ('T')
it works as expected.
Did I miss anything?
Duplicate. The answer, anyway, is to use SUBSTR(FOO, 0, 1) IN ?1 without the parantheses.
You are passing a list as a parameter, thus you should use the setParameterList method:
selectQuery.setParameterList(1, Arrays.asList(new String[] { "T" }));

Bulk save to mongo db using Morphia

I have a list of data object which has to be saved in mongodb.
if datastore.save(ListofObject) is used will it degrade the performance.Morphia version is 1.1.0 and java jdk 1.8
You can do this. Suppose if entity name is User,
Query<User> query = MongoUtils.getDataStore()
.createQuery(User.class)
.filter("active", Boolean.TRUE)
.filter("suspensionDate <", new Date());
UpdateOperations<User> updateOperations = MongoUtils.getDataStore()
.createUpdateOperations(User.class)
.set("active", false);
UpdateResults updateResults = MongoUtils.getDataStore()
.update(query, updateOperations, false, null);
In the above case the all user with flag active true and suspension date less that today will be set with flag active false.
If total records updated need to know then below lines are useful.
WriteResult writeResult = updateResults.getWriteResult();
int totalRecordsUpdated = writeResult.getN();

Lucene.net DeleteDocuments deleting too much?

I have for example two docs in the index...both of them have fields "Id".
Now, I issue a DeleteDocuemnts on IndexWritter giving it the Id of the first item.
So creating the index:
var document = new global::Lucene.Net.Documents.Document();
document.Add(new Field("Content", "content", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
document.Add(new Field("Id", "vladanstrigo", Field.Store.YES, Field.Index.NOT_ANALYZED));
var document2 = new global::Lucene.Net.Documents.Document();
document2.Add(new Field("Content", "content second", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
document2.Add(new Field("Id", "ivanstrigo", Field.Store.YES, Field.Index.NOT_ANALYZED));
var directory = FSDirectory.Open("...directory...");
var analyzer = ...GetAnalyzer();
var indexWriter = ...GetWriter();
indexWriter.AddDocument(document);
indexWriter.AddDocument(document2);
This works great...I get two documents in index and they work perfect.
But when I do:
indexWriter.DeleteDocuments(new Term("Id", "ivanstrigo"));
The IndexWriter deleted ALL documents in index...not only the one matching this term...which I don't know how to stop. I only want to delete this one!
What am I doing wrong?
Found an answer...when creating IndexWriter, I've had "true" on create new index...which basically always recreated a new index.
It works now.