I think this is what I need...

Oct 4, 2012 at 12:01 AM
Edited Oct 4, 2012 at 1:46 AM

I'm working on something where I think I can make use of the roboCAML library. I haven't used it before and I'm not sure if it'll do what I want. I'll give you the backstory. I'm working on a page library with audience targetting. I need to be able to do a GetListItems call to this page library to fetch the items that are targetted to the user.

I do have some server side code that will be sending me the audiences of the current user, which I'm storing in an array. My thought is instead of fetching a slew of items, looping through them to see if the audience guids match which will add a lot of extra data being returned, make it a dynamic CAML query with roboCAML.

My CAML is already getting pretty hairy and I'm wondering if this will help or hurt.

One of my CAML queries is below, I'd need to add N number of contains clauses for the dynamic number of GUIDs I get back from the server to properly fetch the proper items.

iquery = "<Query><Where>"+
           "<And><And>"+
              "<Or>"+
                  "<IsNull><FieldRef Name='StickyDate' /></IsNull>"+
                  "<Lt><FieldRef Name='StickyDate' /><Value Type='DateTime'><Today /></Value></Lt>"+
              "</Or>"+
              "<Leq><FieldRef Name='PubDate' /><Value Type='DateTime'><Today /></Value></Leq>"+
           "</And>"+
           "<Contains><FieldRef Name='Audience' /><Value Type='TargetTo'>"+value+"</Value></Contains>"+
        "</And></Where><OrderBy><FieldRef Name='PubDate' Ascending='FALSE' /></OrderBy></Query>"

 

Coordinator
Oct 4, 2012 at 12:29 AM

I've been working on nested queries in the background. I haven't had much time to invest in getting them working right, although it's definitely in the works.

roboCAML will handle your N number of <Contains> however.  If this portion isn't dynamic:

           "<And><And>"+
              "<Or>"+
                  "<IsNull><FieldRef Name='StickyDate' /></IsNull>"+
                  "<Lt><FieldRef Name='StickyDate' /><Value Type='DateTime'><Today /></Value></Lt>"+
              "</Or>"+
              "<Leq><FieldRef Name='PubDate' /><Value Type='DateTime'><Today /></Value></Leq>"+
           "</And>"+

then you should be able to use the library and make your life easier. You could use the library to handle the <Contains> and then concat the other portion of this query.

Hope that helps!

Cheers,
Matt 

Oct 4, 2012 at 12:49 AM

Yes, that part would be static.

Is RecursiveAll an option? If not, I can keep those hard coded too.

I'll give it a try.

Coordinator
Oct 4, 2012 at 1:16 AM

Sure is. Pass it in as a QueryOption property of your .Query() call. Looking at the docs, it appears I need to update them.  I only offer a RecursiveAll option. 

Cheers,
Matt 

Oct 4, 2012 at 1:45 AM

It only showed recursive in the options and in the source so I wasn't sure.

Thinking about this more though, a mix of hard coded and dynamic built would result in invalid CAML would it not?  The nesting of the Ands and such would get out of whack depending on how many contains operators get passed through.

Coordinator
Oct 4, 2012 at 2:17 AM

I see it in the source here:

http://robocaml.codeplex.com/SourceControl/changeset/view/19629#186715

You are right about the nested query and the output of roboCAML. It's not easy, CAML gives me a headache... I am working on it though, just not sure when it'll be done.


Cheers,
Matt 

Oct 4, 2012 at 4:37 PM
Edited Oct 4, 2012 at 7:52 PM

I'll keep playing around with it and see if it can get me what I want.

As a suggestion, perhaps it could be constructed so that we could define the nesting in a "mathematical" way, like (A && B) && (C || D) where A, B, C, and D would be object references. Not sure if something like that would help in the construction of the nesting. That's where the CAML builders like BIWUG and Strammit fail in that yes they generate CAML, but it isn't the intended CAML based on the right logic.

Or being able to omit filters and assume inheritance (or some other sybmol/breaker). Like being able to do something like

 config.push({filter: "||", op: "isnull", staticName: "StickyDate"}); 
 config.push({op: "<", staticName: "StickyDate", value: "<Today />"});
/* or like this 
 config.push({filter: "++", op: "<", staticName: "StickyDate", value: "<Today />"});
*/
 config.push({filter: "&&", op: "<=", staticName: "PubDate", value: "<Today />"});

and it be able to output markup like

<Where>
 <And>
  <Or>
   <IsNull><FieldRef Name='StickyDate' /></IsNull>
   <Lt><FieldRef Name='StickyDate' /><Value Type='DateTime'><Today /></Value></Lt>
  </Or>
 <Leq><FieldRef Name='PubDate' /><Value Type='DateTime'><Today /></Value></Leq>
 </And>
</Where>