为什么我的 CAML 查询在包含 <Query> 时会失败?
Why is my CAML query failing when it contains <Query>?
我有一个包含很多文档的列表 (> 5000)。我需要从中检索一份特定文件。我使用这个查询:
@"<View>
<Query>
<Where>
<Contains>
<FieldRef Name=""FileLeafRef""/>
<Value Type=""Text"">MyDocumentName</Value>
</Contains>
</Where>
</Query>
<RowLimit>1</RowLimit>
</View>"
然后我收到一个 ServerException,指出该操作被禁止,因为它超过了列表阈值。
但是如果我删除 <Query>
标签:
@"<View>
<RowLimit>1</RowLimit>
</View>"
它有效,并检索了一个文件,遗憾的是这显然不是我想要的文件。
所以我在这里很困惑。为什么会这样?
尝试
Value Type=File
@"<View>
<Query>
<Where>
<Contains>
<FieldRef Name=""FileLeafRef""/>
<Value Type=""File"">MyDocumentName</Value>
</Contains>
</Where>
</Query>
<RowLimit>1</RowLimit>
</View>"
如果您不喜欢手动构建查询,那么以下几个好工具是:
- U2U CAML 查询构建器,它为您提供 UI 用于构建查询。
- CAML.NET 这是一个用于安全构建 CAML 查询的库
在最终找到合适的关键字来询问 Google 之后,我找到了 this question。
问题是我的库中没有字段被索引,因此当我尝试添加带条件的查询时,必须通读所有库才能找到我需要的文档。很明显,如果文档太多,我会得到异常。
<RowLimit>
不会阻止此行为,它仅作用于查询的 结果 。
也就是说,有一个字段是自动索引的:ID。所以我们可以稍微改变一下我们的查询,手动分页 ID 在两个值之间的文档,只需将查询放在 while
循环中,每次分页递增当前 ID,如下所示:
ListItemCollection items = null;
const int paging = 2000;
int currentPaging = paging;
while (items == null || items.Count == 0 || currentPaging < 100000)
{
var query = new CamlQuery
{
ViewXml = $"<View><Query><Where><And><Contains><FieldRef Name='FileLeafRef' /><Value Type='File'>MyDocumentName</Value></Contains><And><Leq><FieldRef Name='ID' /><Value Type='Counter'>{currentPaging}</Value></Leq><Gt><FieldRef Name='ID' /><Value Type='Counter'>{currentPaging - paging}</Value></Gt></And></And></Where></Query></View>"
};
items = list.GetItems(query);
ctx.Load(items);
ctx.ExecuteQuery();
currentPaging += paging;
}
这里是查询中使用的格式化 XML (query.ViewXml
),为了更好的可读性:
<View>
<Query>
<Where>
<And>
<Contains>
<FieldRef Name='FileLeafRef' />
<Value Type='File'>MyDocumentName</Value>
</Contains>
<And>
<Leq>
<FieldRef Name='ID' />
<Value Type='Counter'>{currentPaging}</Value>
</Leq>
<Gt>
<FieldRef Name='ID' />
<Value Type='Counter'>{currentPaging - paging}</Value>
</Gt>
</And>
</And>
</Where>
</Query>
</View>
我有一个包含很多文档的列表 (> 5000)。我需要从中检索一份特定文件。我使用这个查询:
@"<View>
<Query>
<Where>
<Contains>
<FieldRef Name=""FileLeafRef""/>
<Value Type=""Text"">MyDocumentName</Value>
</Contains>
</Where>
</Query>
<RowLimit>1</RowLimit>
</View>"
然后我收到一个 ServerException,指出该操作被禁止,因为它超过了列表阈值。
但是如果我删除 <Query>
标签:
@"<View>
<RowLimit>1</RowLimit>
</View>"
它有效,并检索了一个文件,遗憾的是这显然不是我想要的文件。
所以我在这里很困惑。为什么会这样?
尝试
Value Type=File
@"<View>
<Query>
<Where>
<Contains>
<FieldRef Name=""FileLeafRef""/>
<Value Type=""File"">MyDocumentName</Value>
</Contains>
</Where>
</Query>
<RowLimit>1</RowLimit>
</View>"
如果您不喜欢手动构建查询,那么以下几个好工具是: - U2U CAML 查询构建器,它为您提供 UI 用于构建查询。 - CAML.NET 这是一个用于安全构建 CAML 查询的库
在最终找到合适的关键字来询问 Google 之后,我找到了 this question。
问题是我的库中没有字段被索引,因此当我尝试添加带条件的查询时,必须通读所有库才能找到我需要的文档。很明显,如果文档太多,我会得到异常。
<RowLimit>
不会阻止此行为,它仅作用于查询的 结果 。
也就是说,有一个字段是自动索引的:ID。所以我们可以稍微改变一下我们的查询,手动分页 ID 在两个值之间的文档,只需将查询放在 while
循环中,每次分页递增当前 ID,如下所示:
ListItemCollection items = null;
const int paging = 2000;
int currentPaging = paging;
while (items == null || items.Count == 0 || currentPaging < 100000)
{
var query = new CamlQuery
{
ViewXml = $"<View><Query><Where><And><Contains><FieldRef Name='FileLeafRef' /><Value Type='File'>MyDocumentName</Value></Contains><And><Leq><FieldRef Name='ID' /><Value Type='Counter'>{currentPaging}</Value></Leq><Gt><FieldRef Name='ID' /><Value Type='Counter'>{currentPaging - paging}</Value></Gt></And></And></Where></Query></View>"
};
items = list.GetItems(query);
ctx.Load(items);
ctx.ExecuteQuery();
currentPaging += paging;
}
这里是查询中使用的格式化 XML (query.ViewXml
),为了更好的可读性:
<View>
<Query>
<Where>
<And>
<Contains>
<FieldRef Name='FileLeafRef' />
<Value Type='File'>MyDocumentName</Value>
</Contains>
<And>
<Leq>
<FieldRef Name='ID' />
<Value Type='Counter'>{currentPaging}</Value>
</Leq>
<Gt>
<FieldRef Name='ID' />
<Value Type='Counter'>{currentPaging - paging}</Value>
</Gt>
</And>
</And>
</Where>
</Query>
</View>