我正在尝试在应用程序中实现一些自定义搜索,允许用户键入某些字段和术语并查询结果;例如,有一个文本框,他们可以输入... Name: Stacey
并运行一些代码。
如果他们给它一个有效的名字,那就行得很好。但是,如果他们给它提供的信息无法找到,我会得到一个例外,我无法弄清楚如何阻止它。 try
似乎也不起作用;代码并不复杂,但有点分手。
基本上,这是在从控制器方法接收零个或两个字符串后运行的。第一个字符串是字段,第二个字符串是要查询的值。如果我给它有效的输入,它工作正常;但是其他任何事情都会导致程序崩溃。我能做些什么吗?
冗长的回调过程是因为每个控制器方法需要对结果做出不同的反应,但这与此问题无关。
private JsonResult JsonDataFromDataSourceRequest<T, TIndexCreator>
([DataSourceRequest] DataSourceRequest request,
Func<IDocumentQuery<T>, string, string, IDocumentQuery<T>> search,
Func<IDocumentQuery<T>, IDocumentQuery<T>> sort)
where T : IHasName
where TIndexCreator : Raven.Client.Indexes.AbstractIndexCreationTask, new() {
RavenQueryStatistics statistics;
var query = RavenSession
.Advanced.DocumentQuery<T, TIndexCreator>()
.WhereEquals("collection", typeof(T).RavenCollection())
.WaitForNonStaleResultsAsOfNow()
.Statistics(out statistics); // output our query statistics
// we can accept a sorting system, or additional query options here
if (sort != null)
query = sort(query);
if (request.Filters != null) {
if (request.Filters.Any()) {
var filters = request.Filters.ToFilters();
// determine the field/term to search by
var name = filters.Count > 0 ? filters[0].Value.ToString() : null;
var field = filters.Count > 0 ? filters[0].Member.ToString() : "Name";
if (name != null && !String.IsNullOrEmpty(name)) {
query = query.AndAlso().Search(field, name);
}
}
}
var results = query
.OrderBy(n => n.Name)
.Skip((request.Page - 1) * request.PageSize)
.Take(request.PageSize)
.ToList();
var totalResults = statistics.TotalResults;
return Json(new { data = results, total = totalResults });
}
System.InvalidOperationException
抛出的异常是System.InvalidOperationException
。当我深入研究调试器时,发送到Raven的实际查询的形式为;
{collection:users AND DisplayName: ( Stacey)}
collection
存在是因为此索引用于许多不同的对象,但许多(如果不是全部)对象共享几个相似的字段。将集合作为查询的一部分而不是试图找到在Type
调用中使用Query<T>
的方法似乎更简单。
TModel
来查询?我想避免制作几十个重复索引。当用户尝试查找不在被检查对象类型的字段时,似乎会发生这种情况。
换句话说,即使Owner
被编入索引,如果用户针对查找Owner: Ciel
的页面键入Users
,执行此操作不有Owner
字段(但许多其他类都有),它会抛出此错误。如果他们试图输入一个没有编入索引的字段,它就会这样做。
以下是我正在使用的索引。也许有一种更简单的方法可以在没有collection
字段的情况下做到这一点,但是我并没有意识到这一点(但我仍然缺乏经验)。 有近28个不同的页面,每个页面都有搜索功能。一些实体之间存在许多类似的字段,因此制作28个不同的索引似乎毫无意义。
public class EntityByName : AbstractIndexCreationTask {
public override IndexDefinition CreateIndexDefinition() {
return new IndexDefinition {
Map = @"
from doc in docs
let collection = doc[""@metadata""][""Raven-Entity-Name""]
select new {
doc.Id,
doc.Name,
doc.Owner,
doc.Group,
doc.Email,
Tags = doc.Tags.Select( r => r.Name ),
collection
};",
Indexes ={
{"Id", FieldIndexing.Analyzed},
{"Name", FieldIndexing.Analyzed},
{"Owner", FieldIndexing.Analyzed},
{"Tags", FieldIndexing.Analyzed},
{"Group", FieldIndexing.Analyzed},
{"Email", FieldIndexing.Analyzed}
}
};
}
public override string IndexName {
get { return "Raven/DocumentsByEntity"; }
}
}
这是一个完整的异常消息。
Url: "/databases/dev-isolated/indexes/Raven/DocumentsByEntity?&query=collection%3Ausers%20AND%20Number%3A%28%203%29&pageSize=5&sort=Name&SortHint-collection=String&SortHint-Name=String&cutOff=2015-10-02T15%3A12%3A31.5784892Z&waitForNonStaleResultsAsOfNow=true"
System.ArgumentException: The field 'DisplayName' is not indexed, cannot query on fields that are not indexed
at Raven.Database.Indexing.Index.AssertQueryDoesNotContainFieldsThatAreNotIndexed(IndexQuery indexQuery, AbstractViewGenerator viewGenerator) in c:\Builds\RavenDB-Stable-3.0\Raven.Database\Indexing\Index.cs:line 1130
at Raven.Database.Indexing.Index.IndexQueryOperation.<Query>d__5a.MoveNext() in c:\Builds\RavenDB-Stable-3.0\Raven.Database\Indexing\Index.cs:line 1252
at Raven.Database.Util.ActiveEnumerable`1..ctor(IEnumerable`1 enumerable) in c:\Builds\RavenDB-Stable-3.0\Raven.Database\Util\ActiveEnumerable.cs:line 16
at Raven.Database.Actions.QueryActions.DatabaseQueryOperation.Init() in c:\Builds\RavenDB-Stable-3.0\Raven.Database\Actions\QueryActions.cs:line 245
at Raven.Database.Actions.QueryActions.<>c__DisplayClasse.<Query>b__a(IStorageActionsAccessor accessor) in c:\Builds\RavenDB-Stable-3.0\Raven.Database\Actions\QueryActions.cs:line 118
at Raven.Storage.Esent.TransactionalStorage.ExecuteBatch(Action`1 action, EsentTransactionContext transactionContext) in c:\Builds\RavenDB-Stable-3.0\Raven.Database\Storage\Esent\TransactionalStorage.cs:line 843
at Raven.Storage.Esent.TransactionalStorage.Batch(Action`1 action) in c:\Builds\RavenDB-Stable-3.0\Raven.Database\Storage\Esent\TransactionalStorage.cs:line 807
at Raven.Database.Actions.QueryActions.Query(String index, IndexQuery query, CancellationToken externalCancellationToken) in c:\Builds\RavenDB-Stable-3.0\Raven.Database\Actions\QueryActions.cs:line 108
at Raven.Database.Server.Controllers.IndexController.PerformQueryAgainstExistingIndex(String index, IndexQuery indexQuery, Etag& indexEtag, HttpResponseMessage msg, CancellationToken token) in c:\Builds\RavenDB-Stable-3.0\Raven.Database\Server\Controllers\IndexController.cs:line 625
at Raven.Database.Server.Controllers.IndexController.ExecuteQuery(String index, Etag& indexEtag, HttpResponseMessage msg, CancellationToken token) in c:\Builds\RavenDB-Stable-3.0\Raven.Database\Server\Controllers\IndexController.cs:line 570
at Raven.Database.Server.Controllers.IndexController.GetIndexQueryResult(String index, CancellationToken token) in c:\Builds\RavenDB-Stable-3.0\Raven.Database\Server\Controllers\IndexController.cs:line 541
at Raven.Database.Server.Controllers.IndexController.IndexGet(String id) in c:\Builds\RavenDB-Stable-3.0\Raven.Database\Server\Controllers\IndexController.cs:line 182
at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()
我做了相应的更改,这是该方法的最终结果;
private JsonResult JsonDataFromDataSourceRequest<T, TIndexCreator>
([DataSourceRequest] DataSourceRequest request,
Func<IDocumentQuery<T>, string, string, IDocumentQuery<T>> search,
Func<IDocumentQuery<T>, IDocumentQuery<T>> sort)
where T : IHasName
where TIndexCreator : Raven.Client.Indexes.AbstractIndexCreationTask, new() {
try {
// we need to be able to catch some query statistics to make sure that the
// grid view is complete and accurate, with paging
RavenQueryStatistics statistics;
// try to query the items listing as quickly as we can, getting only the
// page we want out of it
var query = RavenSession
.Advanced.DocumentQuery<T, TIndexCreator>()
.WhereEquals("collection", typeof(T).RavenCollection())
.WaitForNonStaleResultsAsOfNow()
.Statistics(out statistics); // output our query statistics
// we can accept a sorting system, or additional query options here
if (sort != null)
query = sort(query);
// deserialize the contents of the kendo grid filter
if (request.Filters != null) {
if (request.Filters.Any()) {
var filters = request.Filters.ToFilters();
var name = filters.Count > 0 ? filters[0].Value.ToString() : null;
var field = filters.Count > 0 ? filters[0].Member.ToString() : "Name";
if (name != null && !String.IsNullOrEmpty(name)) {
query = search(query, field, name);
}
}
}
// finish constructing the items query
var results = query
.OrderBy(n => n.Name)
.Skip((request.Page - 1) * request.PageSize)
.Take(request.PageSize)
.ToList();
var totalResults = statistics.TotalResults;
return Json(new { data = results, total = totalResults, errors = "" });
}
catch {
// the user tried to ask for something
// that doesn't exist, or a field that
// cannot be queried
var results = new List<T>();
// total results is always 0 on an error
var totalResults = 0;
var errors = new List<string> {
"You have attempted to query an invalid field, or given an inappropriate value."
};
return Json(new { data = results, total = totalResults, errors = errors });
}
}
答案 0 :(得分:2)
错误很明显:
The field 'DisplayName' is not indexed, cannot query on fields that are not indexed