chriseldredge / Lucene.Net.Linq

LINQ provider to run native queries on a Lucene.Net index
Other
151 stars 66 forks source link

Issue with Contains() #73

Closed mahara closed 9 years ago

mahara commented 9 years ago

Hi,

I have an issue with Contains() given the following LINQ:

session.Query().Where(x => ids.Contains(x.Id).ToList();

where ids is a list/collection of document ID to be queried.

Is this a supported scenario?

Here's the exception details:

The binary operator Equal is not defined for the types 'System.Collections.Generic.List`1[System.Int64]' and 'System.Int64'.

--- EXCEPTION #1/1 <InvalidOperationException>
Message = "The binary operator Equal is not defined for the types 'System.Collections.Generic.List`1[System.Int64]' and 'System.Int64'."
ClassName = System.InvalidOperationException
HResult = -2146233079
Source = System.Core
StackTrace =
   at System.Linq.Expressions.Expression.GetEqualityComparisonOperator(ExpressionType binaryType, String opName, Expression left, Expression right, Boolean liftToNull)
   at System.Linq.Expressions.Expression.Equal(Expression left, Expression right, Boolean liftToNull, MethodInfo method)
   at System.Linq.Expressions.Expression.MakeBinary(ExpressionType binaryType, Expression left, Expression right, Boolean liftToNull, MethodInfo method, LambdaExpression conversion)
   at Lucene.Net.Linq.Transformation.TreeVisitors.SubQueryContainsTreeVisitor.VisitSubQueryExpression(SubQueryExpression expression)
   at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitExpression(Expression expression)
   at Remotion.Linq.Clauses.WhereClause.TransformExpressions(Func`2 transformation)
   at Lucene.Net.Linq.Transformation.QueryModelTransformer.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index)
   at Remotion.Linq.Clauses.WhereClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel, Int32 index)
   at Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection`1 bodyClauses, QueryModel queryModel)
   at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
   at Remotion.Linq.QueryModel.Accept(IQueryModelVisitor visitor)
   at Lucene.Net.Linq.LuceneQueryExecutorBase`1.PrepareQuery(QueryModel queryModel)
   at Lucene.Net.Linq.LuceneQueryExecutorBase`1.<ExecuteCollection>d__3`1.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
chriseldredge commented 9 years ago

This is not supported. It could probably be implemented, but Lucene does not support a query like this natively. Probably the approach would be to generate a Boolean query testing a field against each distinct value in the collection.

The best work around at the moment is probably something like:

var query = session.Query();
var docs = ids.Select(i => query.Where(d => d.Id == i).SingleOrDefault()).ToList();

This would execute a single query for each id instead of executing them all in a single query. Without profiling I'm not sure how much advantage there would be to try to do them all in a single query.

mahara commented 9 years ago

IC.

Yup, that's what basically I'm doing, querying document per its ID. I'm just looking for if there were any better and performant way in doing that.

Thanks for the clarification!