Lucence .NET sort by DateTime - lucene.net

I use Lucene.Net.Linq to index data.Lucene.Net.Linq save datetime like
"2015-01-03T09:47:59".
Now how I can sort index using raw Lucence .NET?
I test this but it`s not working :
var sort = new Sort(new SortField("DateTime", SortField.LONG, false));
For your information filtering work with this code :
var dateFilter = new Lucene.Net.Search.TermRangeFilter("DateTime", startDate.ToString("s"),endDate.ToString("s"), true, true);

Related

How to modify the available filter operators of a smart table

I have a smart table that shows data from odata service. all properties of the entity type are Edm.String.
now i can set a filter for each column of the resulting table with a lot of filter operators.
My goal is to filter the list of available filter operators depending on the selected column.
e.g.
selected colum 'A' then allow only 'equal to'.
Is that somehow possible? I would like to solve it in front end code.
I didn't find anything like that in ui5 docu...
you need to use equals FilterOperator
here is a link for FilterOperator and another example how to use filter in grid table https://sapui5.hana.ondemand.com/
Here is a quick example of setting more than one filter each with different Filter Operator
filterGlobally : function(oEvent) {
var sQuery = oEvent.getParameter("query");
this._oGlobalFilter = null;
if (sQuery) {
this._oGlobalFilter = new Filter([
new Filter("columA", FilterOperator.EQ, sQuery),
new Filter("columB", FilterOperator.Contains, sQuery)
], false);
}
var oFilter = null;
if (this._oGlobalFilter) {
oFilter = new Filter([this._oGlobalFilter], true);
}
this.byId("idTable").getBinding().filter(oFilter, "Application");

Looping Over a Java Object and Passing One Field to a Mongo Query Similar to SQL WHERE...IN Clause

I am trying to construct a MongoDB equivalent of an SQL WHERE IN clause by iterating over a Java Object List and using one field in that list to fill in the IN data. Using generic example, I would like to build the following command in MongoDB syntax:
SELECT title FROM albums WHERE recorded_year IN ('1967','1968','1969','1970');
The SQL command IN data is extracted from the Album object recordedYear value using the following loop:
if (albums.size() <= 1000) {
sb.append("SELECT title FROM albums WHERE recorded_year");
sb.append(" IN (");
for (int i = 0; i < albums.size(); i++) {
sb.append("'");
sb.append(albums.get(i).getRecordedYear());
sb.append("'");
if (i < albums.size() - 1) {
sb.append(",");
} else {
sb.append(")");
}
}
}
Most Mongo/Java sites I visited seem to deal with command structures using hard-coded values which, while helpful, is completely impractical in real world applications. Any help in pointing to a good tutorial, or if someone has the actual code itself would be greatly appreciated.
Thanks.
But the issue I am having is understanding how to pass a Java Object
list to the to the getAllDocuments...
Make an array of elements which you want to match with the field using the in operator. For example, If you have a someObject.year field, then the array will have the year values; int [] matchYears = { 1989, 2001, 2012 }. Instead of an array you can also use a List collection.
The query:
Bson queryFilter = in("recordedYear", matchYears);
List<Document> result = new ArrayList<>();
collection.find(queryFilter).into(result);
result.forEach(System.out::println);
The queryFilter is built using the com.mongodb.client.model.Filters factory class.
The MongoDB documentation on using the $in operator.
NOTE: The int [] matchYears = { 1989, 2001, 2012 } can be also be created as
int [] matchYears = { javaObject1.recorded_year, javaObject2.recorded_year, ... }.
I didn't quite implement it with BSON, but the logic in the method appears to be working with the code below. Thank you again for your help.
public void getAlbumYears(MongoCollection<Document> collection, List<Album> albums) {
BasicDBObject inQuery = new BasicDBObject();
List<String> year = new ArrayList<>();
for(Album album : albums) {
year.add(album.getYear());
}
inQuery.put("year", new BasicDBObject("$in", year));
for (Document document : collection.find(inQuery)) {
System.out.println(document.toJson());
}
}

MongoDB : How to find multiple documents and update at the same time?

I have mongo DB and I am using C#.Net to interact with mongo db. C# API has methods for finding a single document and updating it at the same time. For example FindOneAndUpdateAsync.
However I couldn't find any method to find multiple documents and update them at the same time asynchronously.
The code below finding and processing each document asynchronously. How do I also update that document at the same time?
public async Task<IList<IDictionary<string, string>>> DoWork()
{
var collection = _mongoDatabase.GetCollection<BsonDocument>("units");
var filterBuilder = Builders<BsonDocument>.Filter;
var filter = filterBuilder.Ne<string>("status", "INIT") &
(filterBuilder.Exists("isDone", false) |
filterBuilder.Eq<bool>("isDone", false));
// I want to pass this update filter to update the document. But not sure how
var update = Builders<BsonDocument>.Update
.CurrentDate("startTime");
var sort = Builders<BsonDocument>.Sort.Ascending("startTime");
var projection = Builders<BsonDocument>.Projection
.Include("_id")
.Include("fileName"); // for bravity i have removed other projection elements
var output = new List<IDictionary<string, string>>();
// How do i pass update filter and update the document at the same time??
await collection
.Find(filter)
.Sort(sort)
.Project(projection)
.ForEachAsync((unit) =>
{
var dictionary = new Dictionary<string, string>();
Recurse(unit, dictionary);
output.Add(dictionary);
});
return output.Count > 0 ? output : null;
}
That doesn't exist in the mongo .Net api see here.
Just use a combination of Find and UpdateManyAsync.

How to implement search with multiple filters using lucene.net

I'm new to lucene.net. I want to implement search functionality on a client database. I have the following scenario:
Users will search for clients based on the currently selected city.
If the user wants to search for clients in another city, then he has to change the city and perform the search again.
To refine the search results we need to provide filters on Areas (multiple), Pincode, etc. In other words, I need the equivalent lucene queries to the following sql queries:
SELECT * FROM CLIENTS
WHERE CITY = N'City1'
AND (Area like N'%area1%' OR Area like N'%area2%')
SELECT * FROM CILENTS
WHERE CITY IN ('MUMBAI', 'DELHI')
AND CLIENTTYPE IN ('GOLD', 'SILVER')
Below is the code I've implemented to provide search with city as a filter:
private static IEnumerable<ClientSearchIndexItemDto> _search(string searchQuery, string city, string searchField = "")
{
// validation
if (string.IsNullOrEmpty(searchQuery.Replace("*", "").Replace("?", "")))
return new List<ClientSearchIndexItemDto>();
// set up Lucene searcher
using (var searcher = new IndexSearcher(_directory, false))
{
var hits_limit = 1000;
var analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);
// search by single field
if (!string.IsNullOrEmpty(searchField))
{
var parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_30, searchField, analyzer);
var query = parseQuery(searchQuery, parser);
var hits = searcher.Search(query, hits_limit).ScoreDocs;
var results = _mapLuceneToDataList(hits, searcher);
analyzer.Close();
searcher.Dispose();
return results;
}
else // search by multiple fields (ordered by RELEVANCE)
{
var parser = new MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_30, new[]
{
"ClientId",
"ClientName",
"ClientTypeNames",
"CountryName",
"StateName",
"DistrictName",
"City",
"Area",
"Street",
"Pincode",
"ContactNumber",
"DateModified"
}, analyzer);
var query = parseQuery(searchQuery, parser);
var f = new FieldCacheTermsFilter("City",new[] { city });
var hits = searcher.Search(query, f, hits_limit, Sort.RELEVANCE).ScoreDocs;
var results = _mapLuceneToDataList(hits, searcher);
analyzer.Close();
searcher.Dispose();
return results;
}
}
}
Now I have to provide more filters on Area, Pincode, etc. in which Area is multiple. I tried BooleanQuery like below:
var cityFilter = new TermQuery(new Term("City", city));
var areasFilter = new FieldCacheTermsFilter("Area",areas); -- where type of areas is string[]
BooleanQuery filterQuery = new BooleanQuery();
filterQuery.Add(cityFilter, Occur.MUST);
filterQuery.Add(areasFilter, Occur.MUST); -- here filterQuery.Add not have an overloaded method which accepts string[]
If we perform the same operation with single area then it's working fine.
I've tried with ChainedFilter like below, which doesn't seems to satisfy the requirement. The below code performs or operation on city and areas. But the requirement is to perform OR operation between the areas provided in the given city.
var f = new ChainedFilter(new Filter[] { cityFilter, areasFilter });
Can anybody suggest to me how to achieve this in lucene.net? Your help will be appreciated.
You're looking for the BooleanFilter. Almost any query object has a matching filter object.
Look into TermsFilter (from Lucene.Net.Contrib.Queries) if your indexing doesn't match the requirements of FieldCacheTermsFilter. From the documentation of the later; "this filter requires that the field contains only a single term for all documents".
var cityFilter = new FieldCacheTermsFilter("CITY", new[] {"MUMBAI", "DELHI"});
var clientTypeFilter = new FieldCacheTermsFilter("CLIENTTYPE", new [] { "GOLD", "SILVER" });
var areaFilter = new TermsFilter();
areaFilter.AddTerm(new Term("Area", "area1"));
areaFilter.AddTerm(new Term("Area", "area2"));
var filter = new BooleanFilter();
filter.Add(new FilterClause(cityFilter, Occur.MUST));
filter.Add(new FilterClause(clientTypeFilter, Occur.MUST));
filter.Add(new FilterClause(areaFilter, Occur.MUST));
IndexSearcher searcher = null; // TODO.
Query query = null; // TODO.
Int32 hits_limit = 0; // TODO.
var hits = searcher.Search(query, filter, hits_limit, Sort.RELEVANCE).ScoreDocs;
What you are looking for is nested boolean queries so that you have an or (on your cities) but that whole group (matching the or) is itself matched as an and
filter1 AND filter2 AND filter3 AND (filtercity1 OR filtercity2 OR filtercity3)
There is already a good description of how to do this here:
How to create nested boolean query with lucene API (a AND (b OR c))?

Query without condition in MongoDB + C#

I'm trying to use the collection.FindAndModify and give it a IMongoQuery which selects all the documents. But I can not find how to create a query without any conditions!
Can anyone tell me how to do this? I'm using MongoDB C# Driver v1.8.3.
Here's my code:
var query = ???;
var sortBy = SortBy.Ascending(new string[] { "last_update" });
var update = Update<Entity>.Set(e => e.last_update, DateTime.Now);
var fields = Fields.Include(new string[] { "counter", "_id" });
var m = collection.FindAndModify(query, sortBy, update, fields, false, false);
I wonder what should I write in place of ??? to select all the documents!?
Use an empty QueryDocument:
var query = new QueryDocument();
But keep in mind that FindAndModify will only modify the first matching document.