我在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语句似乎不适用?
获取所需数据的正确方法是什么?
答案 0 :(得分:2)
您在查询中使用“ .Select
”,即“ 投影”。
投影只能在处理,过滤,排序和分页文档后用作查询管道中的最后阶段。
因此,您不能在Where
之后应用Select
。
请参阅:Projecting Individual Fields
请参阅:Query Example