Query through SPListCollection - asp.net

I wonder if it's somehow possible to query a SPListCollection object using SPQuery, as with SPListItemCollection. Imagine that you want to find out which lists were created by a given Author or visible for a given user, for example.

No, this is not possible with SPQuery! But i would prefer you using KeywordQuery:
using (SPSite siteCollection = new SPSite("http://server/sitecollection"))
{
KeywordQuery keywordQuery = new KeywordQuery(siteCollection);
keywordQuery.QueryText = "SharePoint";
SearchExecutor searchExecutor = new SearchExecutor();
ResultTableCollection resultTableCollection = searchExecutor.ExecuteQuery(keywordQuery);
var resultTables = resultTableCollection.Filter("TableType", KnownTableTypes.RelevantResults);
var resultTable = resultTables.FirstOrDefault();
DataTable dataTable = resultTable.Table;
}
Within the Keywordquery you could use for example contentclass STSList to retrieve only lists. And in this case when only using contentclass:"STSList" then you would get all lists where the executor has permissions. You can narrow down by adding additional query parameters. SharePoint search is what you are looking for.

Related

Trying To Filter Only Rows That Meet Two Criteria

I promise I have read through the Query information page, but obviously I am missing/misunderstanding something.
I have a Table that has the statuses for multiple departments (the fields are Strings). When a user loads that table I want App Maker to hide jobs that have been finished.
The way we categorize a job as finishes is when:
The Inventory Status = Complete and when the The Delivery Status = Delivered.
Both these conditions need to be met.
Example:
Inventory (Complete) + Delivery (Delivered) = hide
Inventory (In Progress) + Delivery (Delivered) = don't hide
Inventory (Complete) + Delivery (Scheduled) = don't hide
I tried the following, however it hides all the example listed above, not just the first one.
var datasource = app.datasources.SystemOrders;
var inventory = ['Complete'];
var delivery = ['Delivered'];
datasource.query.filters.InventoryStatus._notIn = inventory;
datasource.query.filters.DeliveryStatus._notIn = delivery;
datasource.load();
I have also tried this:
var datasource = app.datasources.SystemOrders;
datasource.query.filters.InventoryStatus._notIn = 'Complete';
datasource.query.filters.DeliveryStatus._notIn = 'Delivered';
datasource.load();
But I get this error:
Type mismatch: Cannot set type String for property _notIn. Type List is expected. at SystemOrders.ToolBar.Button2.onClick:2:46
Any help would be greatly appreciated.
Filters are using AND operator. Please consider switching the Datasource Query Builder and applying the following query:
"InventoryStatus != :CompleteStatus OR DeliveryStatus != :DeliveredStatus"
Set CompleteStatus variable to Complete
Set DeliveredStatus variable to Delivered
Explanation:
Filter you want to apply is "NOT(InventoryStatus = Complete AND DeliveryStatus = Delivered)" which is equivalent to "InventoryStatus != Complete OR DeliveryStatus != Delivered".
Vasyl answer my question perfectly, but I wanted to add a few details in case anyone needs to do the same thing and aren't familiar with using the Datasource Query Builder.
All I did was click the Database I was using and then clicked the Datasources section at the top.
I clicked Add Datasource, named it a new name and pasted Vasyl's code into the Query Builder Expression box.
Two new boxes appear below it allowing me to enter the desired statuses that I wanted to filter out.
Lastly I went back to my Table and changed its datasource to my newly created datasource.
Since you are changing your datasource, if you have any extra code on there it may need to be updated to point to the new datasource.
Example:
I had some buttons that would filter entries for the various departments.
So this:
widget.datasource.query.clearFilters();
var datasource = app.datasources.SystemOrders;
var statuses = ['Complete'];
datasource.query.filters.WarehouseStatus._notIn = statuses;
datasource.load();
had to change to this:
widget.datasource.query.clearFilters();
var datasource = app.datasources.SystemOrders_HideComplete;
var statuses = ['Complete'];
datasource.query.filters.WarehouseStatus._notIn = statuses;
datasource.load();
You can use multiple run and then concatenate their results something like following
/**
* Retrieves records for ActionItems datasource.
* #param {RecordQuery} query - query object of the datasource;
* #return {Array<ActionItems>} user's rating as an array.
*/
function getActionItemsForUser_(query) {
var userRoles = app.getActiveUserRoles();
query.filters.Owner._contains = Session.getActiveUser().getEmail();
var ownerRecords = query.run();
query.clearFilters();
query.filters.AddedBy._contains = Session.getActiveUser().getEmail();
var addedByRecords = query.run();
return addedByRecords.concat(ownerRecords);
}

How Can I Duplicate A Item/Record?

(Deleted my old question to simplify it. )
I enter data in a table, I then want to make an exact duplicate of that data in a new item/record/row*.
*not sure the proper term.
Is there any way to accomplish this?
Sorry for the slow response. Here is what you should do:
Add a "copy" button in the row. In the onClick on that button, add this code:
var createDataSource = widget.datasource.modes.create;
var rowDataSource = widget.datasource;
createDataSource.item.foo = rowDataSource.item.foo;
createDataSource.item.bar = rowDataSource.item.bar;
// And so on for each field
createDataSource.createItem();
You could probably make sure of javascript for-in to loop through all the properties of the item in so you don't have to manually specify each record, but I didn't have time to experiment with this.
Edit:
The above code won't show the copied record in the list immediately, because I used row's create data source, instead of the lists create data source. Try this instead:
var rowDataSource = widget.datasource;
// Instead of using the row datasource for create, explicitly use the data source of your list.
var listDatasource = app.datasources.NameOfYourListsDataSource;
var createDataSource = listDatasource.modes.create;
createDataSource.item.foo = rowDataSource.item.foo;
createDataSource.item.bar = rowDataSource.item.bar;
// And so on for each field
createDataSource.createItem();

Difficulty searching Kentico smart search index on integer field using API

I have a Pages smart search index which uses the Standard analyzer. When I examine the generated index in Luke I can see that integer fields have a specific format. For example, all pages created by global administrator have the documentcreatedbyuserid field set to 10000000053.
Reading the documentation I see that integer fields like this need to be searched using a particular syntax:
+DocumentCreatedByUserID;(int)53;Administrator
However, when I pass this string to the following code as the searchQuery variable I get no results.
// Get search results
var parameters = new SearchParameters()
{
AttachmentOrderBy = "",
AttachmentWhere = "",
CheckPermissions = false,
ClassNames = null,
CombineWithDefaultCulture = false,
CurrentCulture = this.Context.CultureCode,
DefaultCulture = CultureHelper.GetDefaultCultureCode(this.Context.SiteName),
DisplayResults = resultsPerPage,
NumberOfProcessedResults = 100,
Path = startPath,
SearchFor = searchQuery,
SearchInAttachments = false,
SearchIndexes = index,
SearchSort = sort,
StartingPosition = (page - 1) * resultsPerPage,
User = this.Context.User.UserInfo
};
ds = CMS.Search.SearchHelper.Search(parameters);
This same code works fine for text field search queries. Can anyone explain:
Is there anything obvious I'm doing wrong?
What is the purpose of the final part of the +DocumentCreatedByUserID;(int)53;Administrator query. Why should I need to pass a text value here?
The field I actually want to search is a custom page type field called newstypeid, which I can see is storing its value in the same way in the index (e.g. a value of 34 is stored as 10000000034).
In Luke if I query +newstypeid:10000000034 I get results. So maybe an easier solution is to find a way to translate an integer to this Lucene format? (i.e. 34 to 10000000034)
UPDATE WITH SOLUTION
Thanks to #richard-Šůstek for pointing me in the right direction. The following method will return a search clause in the required format:
protected string GetIntegerIdClause(string field, int id)
{
var condition = string.Format("{0}:(int){1}", field, id).ToLower();
return SearchSyntaxHelper.CombineSearchCondition(null, new SearchCondition(condition, SearchModeEnum.ExactPhrase, SearchOptionsEnum.NoneSearch));
}
I think you should use SearchValueConverter class from the namespace CMS.Search. This class has static methods to convert specific data type values (int,datetime,etc.) to it's string representation for search terms construction.
Can you try using something like this to transform the searchQuery?:
var condition = new SearchCondition(null, searchModeEnum, SearchOptionsEnum.FullSearch);
searchQuery = SearchSyntaxHelper.CombineSearchCondition(searchText, condition);
I noticed that Kentico is internally calling this method when passing the value from search text box to SearchParameters. I haven't had a chance to test this though. Maybe some other method in SearchSyntaxHelper would be useful too.

XPODataSource: Select from TableValuedFunctions

Is it possible to select from a tabled-valued function using xpoDataSource instead of selecting from a table.
note: Im using xpoDatasource with serverMode = true
Source - Table Valued Function in XPO (and XAF)?
You can accomplish this task via direct SQL queries. Here is an example:
IDataLayer dal = XpoDefault.GetDataLayer(MSSqlConnectionProvider.GetConnectionString("(local)", "TestDatabase"), AutoCreateOption.None);
Session session = new Session(dal);
SelectedData data = session.ExecuteQueryWithMetadata("SELECT * FROM TrackingItemsModified(2)");
XPDataView view = new XPDataView();
foreach (var row in data.ResultSet[0].Rows) {
view.AddProperty((string)row.Values[0], DBColumn.GetType((DBColumnType)Enum.Parse(typeof(DBColumnType), (string)row.Values[2])));
}
view.LoadData(new SelectedData(data.ResultSet[1]));
GridControl control = new GridControl();
control.DataSource = view;
control.Dock = DockStyle.Fill;
Form form = new Form();
form.Controls.Add(control);
form.ShowDialog();
Reference these:
How to populate an XPServerCollectionSource/InstantFeedbackCollectionSource with a runtime designed SQL statement result?
How to pass a table valued parameter to Session.ExecuteSProc method

Get List of Localized Items

I need to get the list of localized items of a publication programatically using coreservice in tridion. Could any one suggest me.
I would use the GetListXml method and specify a BluePrintChainFilterData filter object.
var subjectId = "[TCM Uri of your item]";
var filter = new BluePrintChainFilterData
{
Direction = BluePrintChainDirection.Down
};
var subjectBluePrintChainList = coreServiceClient.GetListXml(subjectId, filter);
You then still need to verify the localized items from the received list.
This wasn't in my original answer, and probably isn't complete because I don't take into account namespaces, but the following would work to select the localized (not shared) items.
var localizedItems = subjectBluePrintChainList.Elements("Item")
.Where(element => "false".Equals(element.Attribute("IsShared").Value, StringComparison.OrdinalIgnoreCase));
The only way I know is to use search functionality:
var searchQuery = new SearchQueryData();
searchQuery.BlueprintStatus = SearchBlueprintStatus.Localized;
searchQuery.FromRepository = new LinkToRepositoryData{IdRef = "tcm:0-5-1"};
var resultXml = ClientAdmin.GetSearchResultsXml(searchQuery);
var result = ClientAdmin.GetSearchResults(searchQuery);

Resources