Почему мой запрос CAML не работает, если он содержит ‹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>"

Он работает и извлекает один файл, который, к сожалению, не тот, который я хотел, очевидно.

Так что я здесь озадачен. Почему он так себя ведет?


person Kilazur    schedule 26.08.2015    source источник


Ответы (2)


Пытаться

Тип значения = Файл

@"<View>
    <Query>
        <Where>
            <Contains>
                <FieldRef Name=""FileLeafRef""/>
                <Value Type=""File"">MyDocumentName</Value>
            </Contains>
        </Where>
    </Query>
    <RowLimit>1</RowLimit>
</View>"

Если вам не нравится создавать запросы вручную, то есть несколько хороших инструментов: - U2U CAML Query Builder, который предоставляет вам пользовательский интерфейс для создания запроса. - CAML.NET - библиотека для безопасного построения запросов CAML.

person N0mi    schedule 26.08.2015
comment
Та же проблема. Всякий раз, когда мой запрос CAML содержит тег <Query>, он полностью игнорируется, и я получаю свое исключение. - person Kilazur; 27.08.2015
comment
Проголосовали за то, что указали на мою ошибку в типе значения и указали на U2U, что отлично! - person Kilazur; 27.08.2015

В конце концов, найдя подходящие ключевые слова для запроса Google, я обнаружил этот вопрос.

Проблема в том, что ни одно поле в моей библиотеке не индексируется, поэтому, когда я пытаюсь добавить запрос с условиями, необходимо прочитать всю библиотеку, чтобы найти нужный мне документ (-ы). Очевидно, что если документов слишком много, я получаю исключение.

<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>
person Kilazur    schedule 27.08.2015