Multiple filters in Lucene.net - search

How to combine multiple filters within one search?
For example I have record with analyzable field title and not analyzable fields id1, id2, id3, release_date. I want to find all records using specific filters for id1, id2, id3 and release_date; So, I have:
RangeFilter refReleaseDateFilter = new RangeFilter("release_date",
refFromDateTimeTerm.Text(), refToDateTimeTerm.Text(), true, true);
RangeFilter refId1Filter = new RangeFilter("id1",
refFromId1Term.Text(), refToId1Term.Text(), true, true);
RangeFilter refId2Filter = new RangeFilter("id2",
refFromId2Term.Text(), refToId2Term.Text(), true, true);
RangeFilter refId3Filter = new RangeFilter("id3",
refFromId3Term.Text(), refToId3Term.Text(), true, true);
But the method Search of class IndexSearcher does not provide array of filters.
Please help me:) Thank you!:)

You may use something like a ChainedFilter
see.: http://lucene.apache.org/java/2_9_0/api/contrib-misc/org/apache/lucene/misc/ChainedFilter.html
there is also a ChainedFilter in the .net distribution of lucene.
http://www.koders.com/csharp/fidB8682543372DDC9772496D453F39957A94E58466.aspx?s=system#L3
Another option would be to implement it as a port of the java application it is not that much code.

Using a single BooleanQuery worked for me with Lucene.NET 3.0.3:
var filters = new BooleanQuery();
filters.Add(new TermQuery(new Term("ancestor_path", path)), Occur.MUST);
filters.Add(new TermQuery(new Term("resource_type", "page")), Occur.MUST);
var filter = new QueryWrapperFilter(filters);

Related

NetSuite Searching for a Duplicate Email Address

As you can tell from all of my earlier questions I'm attempting to learn some NetSuite Suitescript to truly leverage NetSuite. With that being said I've got to where I can search for the max employee number and then act accordingly. Now what I want to do is to search for an email address to see if the one given is a duplicate. Essentially ensure the workflow will not create a new employee record if an employee record already exists with the email address.
I have the following so far...
function checkDuplicate(givenEmail){
var filters = new nlobjSearchFilter('email', null, givenEmail);
var colums = new nlobjSearchColumn('email');
var results = new nlobjSearchRecord('employee', null, filters, columns);
if(results[0].getValue('email') == null) return false;
else return true;
}
Is there a better/easier way? I'll be testing this out.
Your syntax is a bit off. Based on your script, I suggest apply the following modifications:
function checkDuplicate(givenEmail){
var filters = new nlobjSearchFilter('email', null, 'is', givenEmail);
var results = new nlapiSearchRecord('employee', null, filters);
return (results != null);
}
Since you're just checking if there are any matching results, an nlobjColumn isn't needed. Also, if there aren't any matches, nlapiSearchRecord returns a null.
As an additional note, it seems you're still a bit rough on your SuiteScript (at least with the search APIs), so I suggest looking up "Searching with SuiteScript" in the NetSuite Help Center.

Retrieve related entities of each, using RetrieveMultipleRequest

I'm trying to retrieve a list of entities from CRM, but I'd like to get each one with the related entities. So far, I've the following code:
FilterExpression filterExpression = new FilterExpression();
ConditionExpression condition = new ConditionExpression(Constants.ModifiedOnAttribute, ConditionOperator.GreaterEqual, lastSync);
filterExpression.AddCondition(condition);
QueryExpression query = new QueryExpression()
{
EntityName = entityName,
ColumnSet = new ColumnSet(attributesMetadata.Select(att => att.Name).ToArray<string>()),
Criteria = filterExpression,
Distinct = false,
NoLock = true
};
RetrieveMultipleRequest multipleRequest = new RetrieveMultipleRequest();
multipleRequest.Query = queryExpression;
RetrieveMultipleResponse response = (RetrieveMultipleResponse)proxy.Execute(multipleRequest);
In the variable response, I can see the EntityCollection attribute, but inside, Related entities always come empty.
I'd like to know if it is possible to retrieve the set of a given entities, with the related entities, using RetrieveMultipleRequest, rather than go one by one using RetrieveRequest.
One approach to retreive related entities data - adding LinkEntities to your query. Example below will make you an idea how to make this:
LinkEntity linkEntity = new LinkEntity("email", "new_emails", "activityid", "new_relatedemail", JoinOperator.Inner);
linkEntity.Columns.AddColumn("versionnumber");
linkEntity.Columns.AddColumn("new_emailsid");
linkEntity.EntityAlias = "related";
query = new QueryExpression("email");
query.ColumnSet.AddColumn("activityid");
query.ColumnSet.AddColumn("versionnumber");
query.Criteria.AddCondition("modifiedon", ConditionOperator.NotNull);
query.LinkEntities.Add(linkEntity);
And then you can access attributes from related entities using EntityAlias you specified above:
foreach (Entity entity in entities.Entities)
{
if ((long)(entity["related.versionnumber"] as AliasedValue).Value > 0)
{
stop = false;
}
}
The RetrieveMultipleRequest is for returning multiple instances of a particular type of entity. I have spent a year using the CRM SDK from C# and I have found no way of populating those related entity collections in a single query. This basically leaves you with two options:
Use the AliasedValue as SergeyS recommends. Remember when querying 1:Many relationships, be aware that you could be returning multiple results for the same parent entity. This is what I use most of the time.
Perform a second query for each relationship you want access to. You'll probably get better performance if you can use an IN statement in your second query, based on the results of the first, rather than performing a separate query for each result of the first.
Below is some pseudo code to show the difference.
var contacts = GetContacts();
// One Request to get the cars for the contacts
var cars = GetCarsWhereContactIdIn(contacts.Select( c => c.new_ContactId));
foreach(var c in contacts){
c.new_Cars.AddRange(cars.where(car => car.new_contactId = c.ContactId));
}
// Verses
var contacts = GetContacts();
foreach(var c in contacts){
// One Request for each contact
c.new_Cars.AddRange(GetCarsForContact(c.ContactId));
}

How do I use a linq query as a datasource for TreeView or GridView

I am trying to find a way to use the result from my linq query as a datasource for a TreeView and GridView in C#, without having to save the file first in the server. Have tried various options, but all require that the document is saved as a file first. Can someone please help me out? The code is given below:
XDocument products = new XDocument(
new XDeclaration("1.0", "utf-8", ""),
new XElement("products",
new XElement("product", new XAttribute("id", "p1"),
new XElement("name", "Alpha"),
new XElement("Address", "200 WATERLOO DRIVE"),
new XElement("price",
new XElement("currency", "Rs.")),
new XElement("stock", "19"),
new XElement("country", "USA",
new XElement("state", "California"))),
new XElement("product", new XAttribute("id", "p2"),
new XElement("name", "Beta"),
new XElement("Address", "500 MOUNTBATTEN AVENUE"),
new XElement("price",
new XElement("currency", "Rs.")),
new XElement("stock", "25"),
new XElement("country", "USA",
new XElement("state", "Florida")))));
//create a linq query
var newxml = from f1 in products.Elements("product")
where (string)f1.Element("country").Element("state") != "Florida"
select f1;
//Create an xml document in memory using the linq query
XDocument xdoc = new XDocument(
new XDeclaration("1.0", "utf-8", ""),
new XElement("products"));
xdoc.Element("products").Add(newxml);
//create a datasource for TreeView or GridView using the xml document in memory.
XmlDataSource xmlds = new XmlDataSource();
xmlds.DataFile=xdoc;
TreeView1.DataSource = xmlds;
TreeView1.DataBind();
GridView1.DataSource = xmlds;
GridView1.DataBind();
The part of the code for creating the datasource from xdoc is not working. It can be made to work by saving the file and then calling the file for the datasource, but I want do do this from the memory.
you can use the linq query result directly as datasource.
gridview1.datasource = newxml;
gridview1.databind();
drawback i have encountered is that for e.g sorting to work you will need to implement own sort method.

Many to many relations with ServiceStack.OrmLite

I've been checking ServiceStack's documentation, but I haven't found a way to do many to many relationships with ServiceStack.OrmLite, is it supported? Is there a workaround (without writing raw sql)?
I'd like to have something like this:
Article <- ArticleToTag -> Tag
Thanks!!
It's not implicitly handled automatically for you behind the scenes if that's what you mean? But as OrmLite is just a thin wrapper around ADO.NET interfaces anything is possible.
In OrmLite, by default every POCO maps 1:1 with a table. So if you wanted the table layout you would create it just as it looks in your database, e.g.
var article = new Article { ... };
var tag = new Tag { ... };
var articleTag = new ArticleTag { ArticleId = article.Id, TagId = tag.Id };
db.Insert(article, tag, articleTag);
Although you might want to take advantage of the built-in blobbing in OrmLite where any complex type just gets serialized and stored in a single text field. So you could do something like:
var article = { new Article { Tags = { "A","B","C" } };
Where Tags is just a List<string> and OrmLite will take care of transparently serializing it in the database field for you.

How to use nhibernate ToFuture query with nhibernte linq

Does ToFuture works with nhibernate linq? If so, how do you use it?
Be carefull ToFuture only works if the database driver supports MulitpleQueries. This is only the case in some drivers (eg. MySql, SqlServer) but not in all (eg. Oracle)
Yes it does. Here's a simple example:
var blogs = _session.Query<Blog>()
.Take(30)
.ToFuture();
var blogCount= _session.Query<Blog>()
.ToFutureValue(x => x.Count());
Console.WriteLine(blogCount.Value); // DB is queried here.
Here's an example of where I've used it for a customer search form that displayed paged search results and and a total count of search results. Notice you can reuse an IQueryable to create two futures. The Filter methods built an IQueryable based on what fields the user searched by.
int resultsPerPage = 50;
var query = _session.Query<CustomerSearch>()
.FilterById(model)
.FilterByFirstName(model)
.FilterByLastName(model)
.FilterBySocialSecurityNumber(model)
.FilterByPrimaryPhoneNumber(model);
var futureResults = query
.OrderBy(x => x.Id)
.Skip(model.Page * resultsPerPage)
.Take(resultsPerPage)
.ToFuture();
var futureCount = query.ToFutureValue(x => x.Count());

Resources