RavenDB Linq查询在“选择”之后忽略“ Where”和“ OrderBy”语句

时间:2019-10-22 13:11:22

标签: ravendb

我在RavenDB实例中有一个文档列表。这些文档有一个嵌套对象列表,其中包含一个字符串格式的数字值。我需要在此列表的特定嵌套对象中找到具有最高价值的文档。我无法控制文档的布局。

这是我正在使用的查询以及测试数据的简化版本:

using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Raven.Client.Documents;
using Raven.Client.Documents.Session;
using Raven.Embedded;

namespace RavenTest
{
    class Program
    {
        static void Main(string[] args)
        {
            EmbeddedServer.Instance.StartServer();
            using (var store = EmbeddedServer.Instance.GetDocumentStore("Embedded"))
            {
                GenerateTestData(store);
                QueryForEmployeeWithHighestGenericDataValue(store);
            }
        }

        private static void QueryForEmployeeWithHighestGenericDataValue(IDocumentStore store)
        {
            using (var session = store.OpenSession())
            {
                var query = session.Query<Employee>()
                    .Where(x => x.NestedGenericData != null)
                    .Where(x => x.NestedGenericData.Any(y => y.Key == "SomeKeyToFind"))
                    .Select(x =>
                        new
                        {
                            Value = x.NestedGenericData.First(y => y.Key == "SomeKeyToFind").Value,
                            Employee = x.FirstName
                        })
                    .Where(x => x.Value != null)
                    .OrderByDescending(x => x.Value, OrderingType.AlphaNumeric);

                var employeeWithHighestValue = query.FirstOrDefault();

                if (employeeWithHighestValue.Value != "42")
                {
                    var allObjectsOrderedWithoutNulls = JsonConvert.SerializeObject(
                        query.ToList(),
                        new JsonSerializerSettings { Formatting = Formatting.Indented });

                    throw new Exception($"Should be 42, but is {employeeWithHighestValue.Value}");
                }
            }
        }

        private static void GenerateTestData(IDocumentStore store)
        {
            using (var session = store.OpenSession())
            {
                // generate Id automatically
                session.Store(new Employee
                {
                    FirstName = "John10",
                    NestedGenericData = new List<GenericData>
                        {
                            new GenericData
                            {
                                Key = "SomeKeyToFind",
                                Value = "10"
                            },
                        }
                });
                session.Store(new Employee
                {
                    FirstName = "JohnNull",
                    NestedGenericData = new List<GenericData>
                        {
                            new GenericData
                            {
                                Key = "SomeKeyToFind",
                                Value = null
                            },
                        }
                });
                session.Store(new Employee
                {
                    FirstName = "John3",
                    NestedGenericData = new List<GenericData>
                        {
                            new GenericData
                            {
                                Key = "SomeKeyToFind",
                                Value = "3"
                            },
                        }
                });
                session.Store(new Employee
                {
                    FirstName = "John42",
                    NestedGenericData = new List<GenericData>
                        {
                            new GenericData
                            {
                                Key = "SomeKeyToFind",
                                Value = "42"
                            },
                        }
                });
                session.Store(new Employee
                {
                    FirstName = "JohnNoGenericData",
                    NestedGenericData = new List<GenericData>
                        {
                            new GenericData
                            {
                                Key = "SomeOtherKey",
                                Value = "123"
                            },
                        }
                });
                session.Store(new Employee
                {
                    FirstName = "John1",
                    NestedGenericData = new List<GenericData>
                        {
                            new GenericData
                            {
                                Key = "SomeKeyToFind",
                                Value = "1"
                            },
                            new GenericData
                            {
                                Key = "SomeOtherKey",
                                Value = "123"
                            },
                        }
                });

                // send all pending operations to server, in this case only `Put` operation
                session.SaveChanges();
            }
        }
    }

    internal class GenericData
    {
        public string Key { get; set; }
        public string Value { get; set; }
    }

    internal class Employee
    {
        public string FirstName { get; set; }
        public List<GenericData> NestedGenericData { get; set; }
    }
}

如果将此代码粘贴到安装并执行了Install-Package RavenDB.Embedded -Version 4.1.0的新.NET Core控制台应用程序中,则会返回employeeWithHighestValue,其Value字段等于"10",并且{ {1}}字段等于Employee

"John10"的值(即整个查询的转储)将包含以下内容:

allObjectsOrderedWithoutNulls

这既没有过滤掉[ { "Value": "10", "Employee": "John10" }, { "Value": null, "Employee": "JohnNull" }, { "Value": "3", "Employee": "John3" }, { "Value": "42", "Employee": "John42" }, { "Value": "1", "Employee": "John1" } ] 的投影条目,也没有按x.Value == null字段降序排列(字母数字或其他方式)。

问题:

我的查询出了什么问题?

为什么Value之后的LINQ语句似乎不适用?

获取所需数据的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

您在查询中使用“ .Select”,即“ 投影”。

投影只能在处理,过滤,排序和分页文档后用作查询管道中的最后阶段。 因此,您不能在Where之后应用Select

请参阅:Projecting Individual Fields

请参阅:Query Example