SharePoint CAML query - order of Where conditions giving different results - sharepoint

I am experiencing issues in SharePoint Online with a large document list which contains thousands of records. I am getting the usual list view exceeds 5000 items error for some views, so I am trying to filter these views by a date field. I am seeing some strange results that change based on the order of my where conditions.
When I order by the "Event Date" AND "Division" fields, the query is successful.
<View Scope=\"RecursiveAll\">
<Query>
<OrderBy Override='TRUE'><FieldRef Name='ID' /></OrderBy>
<Where>
<And>
<Geq><FieldRef Name='Event_x0020_Date' /><Value Type='DateTime'>2019-01-01T00:00:00Z</Value></Geq>
<Eq><FieldRef Name='Division' /><Value Type='Text'>{division}</Value></Eq>
</And>
</Where>
</Query>
When I perform the exact same query, but the conditions reversed, I get an error that the view exceeds the list view threshold.
<View Scope=\"RecursiveAll\">
<Query>
<OrderBy Override='TRUE'><FieldRef Name='ID' /></OrderBy>
<Where>
<And>
<Eq><FieldRef Name='Division' /><Value Type='Text'>{division}</Value></Eq>
<Geq><FieldRef Name='Event_x0020_Date' /><Value Type='DateTime'>2019-01-01T00:00:00Z</Value></Geq>
</And>
</Where>
</Query>
It seems to me that SharePoint determines that the first condition is already over 5000 items and just does not bother with the 2nd condition. Am I missing something?

In a SharePoint query you will hit the 5000 item threshold if the first filter returns more than 5000 items. Each condition will be evaluated individually, before the second condition of the AND is applied.
If you have more than 5000 items that have the same division, then you can't use that as the first condition. But if the event date applies to fewer than 5000 items, you can use that as the first condition and then add the division condition with AND.
So, yes, the order of the conditions does matter.

Related

how to get double records in SharePoint CAML query?

I've created a View and did group by on a field and then did count on that field. It gives me all records and the total counts. I want to show only records which are greater than 1.... where to put this Greater than in the code ?
I created the view and I opened the view in SharePoint designer and my code looks like this now? I want to put somewhere count(Commitment_x0020_Reference) > 1
<XmlDefinition>
<View Name="{358474DF-DB87-423E-A795-6C361A33655F}" MobileView="TRUE" Type="HTML" DisplayName="Double SI" Url="/networks/SCP/Lists/Contracts and Studies/Double SI.aspx" Level="1" BaseViewID="1" ContentTypeID="0x" ImageUrl="/_layouts/15/images/generic.png?rev=23" >
<Query>
<GroupBy Collapse="TRUE" GroupLimit="500">
<FieldRef Name="Commitment_x0020_Reference"/>
</GroupBy>
<OrderBy>
<FieldRef Name="Date_x0020_of_x0020_Reception" Ascending="FALSE"/>
<FieldRef Name="Modified" Ascending="FALSE"/>
</OrderBy>
</Query>
<ViewFields>
<FieldRef Name="ID"/>
<FieldRef Name="Edit"/>
<FieldRef Name="Type_x0020_of_x0020_Procedures"/>
<FieldRef Name="Unit"/><FieldRef Name="Reference"/><FieldRef Name="Title1"/><FieldRef Name="_x0039_i_x002d_Com_x0020_L2_x002"/><FieldRef Name="Modified"/><FieldRef Name="Editor"/><FieldRef Name="_UIVersionString"/>
</ViewFields>
<RowLimit Paged="TRUE">50</RowLimit>
<Aggregations Value="On">
<FieldRef Name="Commitment_x0020_Reference" Type="COUNT"/>
</Aggregations>
<JSLink>clienttemplates.js</JSLink>
<XslLink Default="TRUE">main.xsl</XslLink>
<Toolbar Type="Standard"/>
</View>
The short answer is that you can't. Querying by the sum of grouped results is not possible with a single CAML query.
Alternate options would be to perform post-processing on the results, so the query returns all records, then you remove the unwanted records on the client side, such as with JavaScript; or you could perform multiple queries in sequence to retrieve every possible value for Commitment_x0020_Reference, then perform multiple queries using those values to retrieve and count the number of results for each Commitment_x0020_Reference value.
Neither of those options is very straightforward to implement from the SharePoint Designer GUI, and may warrant a separate Stack Overflow question depending on your approach.

SharePoint 2013 CAML query OrderBy not sorting properly

I'm using a CAML query to grab some items from a list. It pulls the items into a datatable which is then set as the datasource of a gridview control.
Everything worked fine until I realized it was using the ID field to sort the items. I wanted to sort by the field Target_x0020_Id, so I ordered the order by, however it doesn't change the behavior when I added this.
This is my query:
WhereEqFieldRefName='Target_x0020_Id' Value Type='Text'900/Value/EqWhereOrderByFieldRef Name='Target_x0020_Id'/FieldRef/OrderBy
The only thing I added was the orderby element. (Sorry I'm having some issues posting the code without it trying to render in the post)
I can only assume this is the CAML you're using
<Where>
<Eq>
<FieldRefName='Target_x0020_Id'>
<Value Type='Text'>900</Value>
</Eq>
<Where>
<OrderBy>
<FieldRef Name='Target_x0020_Id'></FieldRef>
</OrderBy>
I see three glaring errors.
There's a missing space between FieldRef and Name in the <Eq> portion of the caml.
The closing <where> is missing the forward slash.
The FieldRef tag in <OrderBy> is incorrect. It's self closing
This should be the right caml
<Where>
<Eq>
<FieldRef Name='Target_x0020_Id'>
<Value Type='Text'>900</Value>
</Eq>
</Where>
<OrderBy>
<FieldRef Name='Target_x0020_Id' />
</OrderBy>
I do see that you're returning all items where Target_x0020_Id is equal to 900 and then sorting all those items by Target_x0020_Id. Since this field is always 900, your sort isn't going to work.
Also, is Target_x0020_Id really a text field? If it's numeric, you should chagne the type to 'Number' instead of 'Text'.

how to make sharepoint CAML query works more efficienctly

I am now working on sharepoint CAML query. to fetch out item by a given name from a huge resources library which full of images, documents, videos and so on.
I didn't know whether sharepoint index the Name column. I'm thinking to use nested query to make this query faster.
My question here is:
How does sharepoint query work? execute the outer layer first, or start from the inner layer?
I wanna to filter the ResourceType(Image,Document..) first. then filter the category and finally fetch out the items match the name.Is the query bellow work just like what i need?
<Where>
<And>
<Eq><FieldRef Name='IR_ResourcesType' />
<Value Type='Text'>Image</Value></Eq>
<And>
<Eq><FieldRef Name='IR_Category' />
<Value Type='Text'>All</Value>
</Eq>
<Eq>
<FieldRef Name='FileLeafRef' />
<Value Type='File'>aaa</Value>
</Eq>
</And>
</And>
</Where>
If you can, try indexing one of the unique columns in your list so you can use it later on for querying in your where clause.
As best practice, we should also just get the columns that we will be using so as to not have a data buffet. You can limit the columns you will be displaying by using viewFields.
Here is a link which shows some tips and tricks for CAML in conjunction with SPServices which I think you might find useful.

Get items from sharepoint list by Title field with ignore care using Caml or SPQuery

I want to get data from SharePoint List using CAML and filtered by Title with ignore case like
<Query>
<Where>
<Eq>
<FieldRef Name='Title' />
<Value Type='Text'>Car</Value>
</Eq>
</Where>
</Query>
But with ignore case so if i have an item with title: car the caml should return it
how can I do this?
I found out it's ignoring case by default.

CAML queries: how to filter folders from result set?

I'm using caml query to select all documents which were modified or added by user. Query runs recursively on all subsites of specified site collection.
Now problem is I can't get rid of folders which are also part of result set. For now I'm filtering them from result datatable. But I'm wondering: Is it possible to filter out folders from result set just by using caml?
This CAML actually does the trick:
<Where>
<Eq>
<FieldRef Name='FSObjType' />
<Value Type='Integer'>0</Value>
</Eq>
</Where>
that will not give you any folders.
So, i figured it out :)
You can use FieldRef='ContentType' in your caml query and specify typr of content type which you want to select or exclude from select.
So in my case I've added this condition to my caml expression:
<Neq><FieldRef Name='ContentType' /><Value Type='Text'>Folder</Value></Neq>
NOTE:
There are problems in multi language setup. Name of content type can be different, so it is good to get names of content types from resources
UPDATE:
It looks like I was too quick in my assumptions. I need to filter out all contett types based on folder content type, because in our projects such content types are used :(
I was not able to create workable query in caml, so I added view field element to my query which selects ContentTypeId of list item and I filter-out rows which are based on folder content type.
Code to do this is trivial, but it bothers me that such simple task cannot be done by pure caml.
If you're working with folders and you're using an SPQuery object you also may want to use the ViewAttributes field to allow for recursive item retrieval. Setting the value to Scope="Recursive" will retrieve items from subfolders and will not retrieve the folder objects in the result set.
myQuery.ViewAttributes = "Scope=\"Recursive\"";
According to the output from CAML Designer (created by Karine Bosch and Andy Van Steenbergen and distributed by the Belux Information Worker User Group) the correct CAML syntax is:
<Where>
<Eq>
<FieldRef Name='FSObjType' />
<Value Type='Integer'>0</Value>
</Eq>
</Where>
<QueryOptions>
<ViewAttributes Scope='RecursiveAll' />
</QueryOptions>
I tested this in PowerShell and got the expected result:
$qry = new-object Microsoft.SharePoint.SPQuery
$qry.Query = "<Where><Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>0</Value></Eq></Where><QueryOptions><ViewAttributes Scope='RecursiveAll' /></QueryOptions>"
$items = $lib.GetItems($qry)
$items.Count
You can replace the <QueryOptions> tag in the CAML with the SPQuery object property ViewAttributes if you prefer, ie $qry.ViewAttributes = “Scope=’RecursiveAll’".
When testing this be sure to re-instantiate the SPQuery object each time as you cannot simple reassign the Query property. Once the query has been executed, any new value assigned to the Query property is ignored. So execute the entire PowerShell fragment.
Dave T.'s answer didn't work for me but taking it as an inspiration here's what I came up with:
<Where>
<BeginsWith><FieldRef Name="ContentTypeId" />
<Value Type="ContentTypeId">0x0101</Value>
</BeginsWith>
</Where>
The main problem is that we can only know ContentTypeId on a site level, because when a content type gets added to a list/library it becomes a list content type and its ID is appended with another GUID (0x010100...). And there's no NotBeginsWith condition in CAML, so we can not filter out folders, but we can include documents only which site content type id is 0x0101.
The solutions with FSObjType field don't work for me because I have libraries with far more files than a threshold so all the fields in the query must be indexed and I haven't found a way to index this field.
This is what worked for me
<Where>
<Eq>
<FieldRef Name='FSObjType' />
<Value Type='Number'>1</Value>
</Eq>
</Where>
Check my other answer CAML query that includes folders in result set
Simply changing the operators might get you what you need
<Where>
<NotIncludes>
<FieldRef Name='ContentTypeId' />
<Value Type='ContentTypeId'>0x0120</Value>
</NotIncludes>
</Where>
I'm not sure if that'll work.
For me also it worked as written below:-
<Where><Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>1</Value></Eq></Where>

Resources