【问题标题】:Creating a completely dynamic query with RavenDB using LuceneQuery使用 LuceneQuery 使用 RavenDB 创建完全动态的查询
【发布时间】:2013-04-01 17:17:50
【问题描述】:

我想要一种可以查询整个 RavenDB 数据库的方法。

我的方法签名如下所示:

public static DataTable GetData(string className, int amount, string orderByProperty, string filterByProperty, string filterByOperator, string filterCompare)

我认为我可以使用动态 LuceneQuery 完成以上所有工作。

session.Advanced.LuceneQuery<dynamic>();

问题是:由于我在给定类型中使用dynamic,如何确保查询只包含与className匹配的类型?

我正在寻找类似 @​​987654324@ 或 .Where("type: " + className) 的内容。

解决方案

这会返回正确类型的结果:

var type = Type.GetType("Business.Data.DTO." + className);

var tagName = RavenDb.GetTypeTagName(type);
using (var session = RavenDb.OpenSession())
{
    var result = session.Advanced
                        .LuceneQuery<object, RavenDocumentsByEntityName>()
                        .WhereEquals("Tag", tagName)
                        .ToList();
}

请注意,无法为此添加额外的“WhereEquals”或其他过滤器。这是因为“RavenDocumentByEntityName”索引中不包含特定于该文档类型的任何内容。

这意味着这个解决方案不能用于我想要完成的事情。

我最终做了什么

虽然它不能完全满足我的要求,但这就是我最终要做的:

public static List<T> GetData<T>(DataQuery query)
{
    using (var session = RavenDb.OpenSession())
    {
        var result = session.Advanced.LuceneQuery<T>();

        if (!string.IsNullOrEmpty(query.FilterByProperty))
        {
            if (query.FilterByOperator == "=")
            {
                result = result.WhereEquals(query.FilterByProperty, query.FilterCompare);
            }
            else if (query.FilterByOperator == "StartsWith")
            {
                result = result.WhereStartsWith(query.FilterByProperty, query.FilterCompare);
            }
            else if (query.FilterByOperator == "EndsWith")
            {
                result = result.WhereEndsWith(query.FilterByProperty, query.FilterCompare);
            }
        }

        if (!string.IsNullOrEmpty(query.OrderByProperty))
        {
            if (query.Descending)
            {
                result = result.OrderBy(query.OrderByProperty);
            }
            else
            {
                result = result.OrderByDescending(query.OrderByProperty);
            }
        }

        result = result.Skip(query.Skip).Take(query.Amount);

        return result.ToList();
    }
}

虽然这肯定是一种反模式,但如果您想要的话,它是一种查看一些数据的巧妙方法。它很容易像这样调用:

DataQuery query = new DataQuery
{
    Amount = int.Parse(txtAmount.Text),
    Skip = 0,
    FilterByProperty = ddlFilterBy.SelectedValue,
    FilterByOperator = ddlOperator.SelectedValue,
    FilterCompare = txtCompare.Text,
    OrderByProperty = ddlOrderBy.SelectedValue,
    Descending = chkDescending.Checked
};

grdData.DataSource = DataService.GetData<Server>(query);
grdData.DataBind();

“服务器”是我正在使用的类/文档类型之一,因此它不是完全动态的缺点是我必须定义这样的调用对于每种类型。

【问题讨论】:

    标签: c# ravendb lucene.net


    【解决方案1】:

    我强烈建议你不要走这条路。您实际上是在尝试隐藏 RavenDB Session 对象,该对象非常强大并且可以直接使用。

    仅查看您要创建的方法的签名,参数都非常严格,并且对您正在处理的数据做出了许多可能不正确的假设。还有返回类型——你为什么要返回DataTable?可能会返回 objectdynamic,但 Raven 中的任何内容都不是在表格中结构化的,所以 DataTable 是个坏主意。

    要回答具体问题,类型名称来自 Raven-Entity-Name 元数据,您需要在其上构建索引。当您在索引中使用from docs.YourEntity 语法进行索引时,这会自动发生。当您使用动态索引(例如 .Query&lt;YourEntity&gt;.Advanced.LuceneQuery&lt;YourEntity&gt;)时,Raven 会在后台执行此操作。

    不过,你不应该这样做。

    【讨论】:

    • 我已经在我的应用程序的其余部分中完成了所有正常的 RavenDB 工作。现在,我想要一种简单快捷的方式,在我开发和测试新功能时直接从我的 Web 应用程序中查看我的数据。
    • 你能帮我理解我是如何在基于文本的 LuceneQuery 中使用 Raven-Entity-Type 的吗?
    • 这完全取决于您正在编写什么样的网络应用程序。例如,您可以创建一个 WebAPI 控制器并将 IQueryable 公开为 OData 端点并从 jQuery 中使用它。或者您可能只是将结果转储到 ASP.Net 页面。也许你应该问一个更具体的问题。
    • 对不起,错字。元数据值称为Raven-Entity-Name。您需要先对其进行索引。请参阅 this post 查询内置的 RavenDocumentsByEntityName 索引。
    • 感谢您的宝贵时间,马特。我认为暗示我上面使用的session 是一个 RavenDb 会话,我从我的 C# 代码中得到这样的结果:_documentStore.OpenSession()。那么无论我使用jQuery还是其他什么都无关紧要,我只需要在编译时不说明实体就取出数据。我将尝试使用您链接到的答案中的示例。谢谢。看起来很有希望。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-31
    • 2013-09-16
    • 1970-01-01
    • 2019-02-09
    • 2021-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多