为什么我的 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>