How to Advance filter for category and author in Smartsearch in kentico - asp.net

I have created basic search and uses the SearchHelper to get smart search results based on the search paramaters.
Now creating the Advance search based on Category , Author etc but did not find the way to filter the result based on these condition.
I am looking for a way to display the results using the dataset that
// Prepare parameters
SearchParameters parameters = new SearchParameters()
{
SearchFor = searchText,
SearchSort = SearchHelper.GetSort(srt),
Path = path,
ClassNames = DocumentTypes,
CurrentCulture = culture,
DefaultCulture = defaultCulture,
CombineWithDefaultCulture = CombineWithDefaultCulture,
CheckPermissions = CheckPermissions,
SearchInAttachments = SearchInAttachments,
User = (UserInfo)CMSContext.CurrentUser,
SearchIndexes = Indexes,
StartingPosition = startPosition,
DisplayResults = displayResults,
NumberOfProcessedResults = numberOfProceeded,
NumberOfResults = 0,
AttachmentWhere = AttachmentsWhere,
AttachmentOrderBy = AttachmentsOrderBy,
BlockFieldOnlySearch = BlockFieldOnlySearch,
};
// Search
DataSet results = SearchHelper.Search(parameters);

The easiest way is to use the method:
SearchHelper.CombineSearchCondition()
The first parameter is the searchText, with the search terms you probably already have.
The second parameter is searchConditions, which can be formatted as per https://docs.kentico.com/k10/configuring-kentico/setting-up-search-on-your-website/smart-search-syntax
Alternatively you could just append your search conditions to your search text manually, separating each term with a space.
Remember that to filter based on any field they need to be selected as searchable in the SiteManager->Development->DocumentTypes->DocumentType->Search Tab.

Related

DynamoDB Xcode6 Swift using three columns as key

I am trying to use a DynamoDB table to store this data:
DartsPlayerInsultTable
CustomerId String
PlayerId String
PlayerInsult String
Using the method (concept, not code) described here:
https://java.awsblog.com/post/Tx3GYZEVGO924K4/The-DynamoDBMapper-Local-Secondary-Indexes-and-You
here:
http://mobile.awsblog.com/post/TxTCW7KW8BGZAF/Amazon-DynamoDB-on-Mobile-Part-4-Local-Secondary-Indexes
and here:
http://labs.journwe.com/2013/12/15/dynamodb-secondary-indexes/comment-page-1/#comment-116
I want to have multiple insult records per customer-player.
CustomerId is my Hash Key
PlayerId is my Range Key
and I a trying to use PlayerInsult in a key so that
a second PlayerInsult value inserts a second record
rather than replacing the existing one.
Have tried both Global and Secondary indexes for this,
but if I try to add a row with a new insult, it still
replaces the insult with the same customer-player key
rather than adding a new one.
Any suggestions on the best approach to use for this is
DynanoDB? Do I need to create a hybrid column for a range-key?
Trying to keep this simple...
class func createDartsPlayerInsultTable() -> BFTask {
let dynamoDB = AWSDynamoDB.defaultDynamoDB()
let hashKeyAttributeDefinition = AWSDynamoDBAttributeDefinition()
hashKeyAttributeDefinition.attributeName = "CustomerId"
hashKeyAttributeDefinition.attributeType = AWSDynamoDBScalarAttributeType.S
let hashKeySchemaElement = AWSDynamoDBKeySchemaElement()
hashKeySchemaElement.attributeName = "CustomerId"
hashKeySchemaElement.keyType = AWSDynamoDBKeyType.Hash
let rangeKeyAttributeDefinition = AWSDynamoDBAttributeDefinition()
rangeKeyAttributeDefinition.attributeName = "PlayerId"
rangeKeyAttributeDefinition.attributeType = AWSDynamoDBScalarAttributeType.S
let rangeKeySchemaElement = AWSDynamoDBKeySchemaElement()
rangeKeySchemaElement.attributeName = "PlayerId"
rangeKeySchemaElement.keyType = AWSDynamoDBKeyType.Range
/*
let indexRangeKeyAttributeDefinition = AWSDynamoDBAttributeDefinition()
indexRangeKeyAttributeDefinition.attributeName = "PlayerInsult"
indexRangeKeyAttributeDefinition.attributeType = AWSDynamoDBScalarAttributeType.S
let rangeKeySchemaElement = AWSDynamoDBKeySchemaElement()
rangeKeySchemaElement.attributeName = "PlayerId"
rangeKeySchemaElement.keyType = AWSDynamoDBKeyType.Range
let indexRangeKeyElement = AWSDynamoDBKeySchemaElement()
indexRangeKeyElement.attributeName = "PlayerInsult"
indexRangeKeyElement.keyType = AWSDynamoDBIndexRangeKeyType.
*/
//Add non-key attributes
let playerInsultAttrDef = AWSDynamoDBAttributeDefinition()
playerInsultAttrDef.attributeName = "PlayerInsult"
playerInsultAttrDef.attributeType = AWSDynamoDBScalarAttributeType.S
let provisionedThroughput = AWSDynamoDBProvisionedThroughput()
provisionedThroughput.readCapacityUnits = 5
provisionedThroughput.writeCapacityUnits = 5
// CREATE GLOBAL SECONDARY INDEX
/*
let gsi = AWSDynamoDBGlobalSecondaryIndex()
let gsiArray = NSMutableArray()
let gsiHashKeySchema = AWSDynamoDBKeySchemaElement()
gsiHashKeySchema.attributeName = "PlayerId"
gsiHashKeySchema.keyType = AWSDynamoDBKeyType.Hash
let gsiRangeKeySchema = AWSDynamoDBKeySchemaElement()
gsiRangeKeySchema.attributeName = "PlayerInsult"
gsiRangeKeySchema.keyType = AWSDynamoDBKeyType.Range
let gsiProjection = AWSDynamoDBProjection()
gsiProjection.projectionType = AWSDynamoDBProjectionType.All;
gsi.keySchema = [gsiHashKeySchema,gsiRangeKeySchema];
gsi.indexName = "PlayerInsult";
gsi.projection = gsiProjection;
gsi.provisionedThroughput = provisionedThroughput;
gsiArray .addObject(gsi)
*/
// CREATE LOCAL SECONDARY INDEX
let lsi = AWSDynamoDBLocalSecondaryIndex()
let lsiArray = NSMutableArray()
let lsiHashKeySchema = AWSDynamoDBKeySchemaElement()
lsiHashKeySchema.attributeName = "CustomerId"
lsiHashKeySchema.keyType = AWSDynamoDBKeyType.Hash
let lsiRangeKeySchema = AWSDynamoDBKeySchemaElement()
lsiRangeKeySchema.attributeName = "PlayerInsult"
lsiRangeKeySchema.keyType = AWSDynamoDBKeyType.Range
let lsiProjection = AWSDynamoDBProjection()
lsiProjection.projectionType = AWSDynamoDBProjectionType.All;
lsi.keySchema = [lsiHashKeySchema,lsiRangeKeySchema];
lsi.indexName = "PlayerInsult";
lsi.projection = lsiProjection;
//lsi.provisionedThroughput = provisionedThroughput;
lsiArray .addObject(lsi)
//Create TableInput
let createTableInput = AWSDynamoDBCreateTableInput()
createTableInput.tableName = DartsPlayerInsultTableName;
createTableInput.attributeDefinitions = [hashKeyAttributeDefinition, rangeKeyAttributeDefinition, playerInsultAttrDef]
//createTableInput.attributeDefinitions = [hashKeyAttributeDefinition, rangeKeyAttributeDefinition]
createTableInput.keySchema = [hashKeySchemaElement, rangeKeySchemaElement]
createTableInput.provisionedThroughput = provisionedThroughput
//createTableInput.globalSecondaryIndexes = gsiArray as [AnyObject]
createTableInput.localSecondaryIndexes = lsiArray as [AnyObject]
return dynamoDB.createTable(createTableInput).continueWithSuccessBlock({ (var task:BFTask!) -> AnyObject! in
if ((task.result) != nil) {
// Wait for up to 4 minutes until the table becomes ACTIVE.
let describeTableInput = AWSDynamoDBDescribeTableInput()
describeTableInput.tableName = DartsPlayerInsultTableName;
task = dynamoDB.describeTable(describeTableInput)
for var i = 0; i < 16; i++ {
task = task.continueWithSuccessBlock({ (task:BFTask!) -> AnyObject! in
let describeTableOutput:AWSDynamoDBDescribeTableOutput = task.result as! AWSDynamoDBDescribeTableOutput
let tableStatus = describeTableOutput.table.tableStatus
if tableStatus == AWSDynamoDBTableStatus.Active {
return task
}
sleep(15)
return dynamoDB .describeTable(describeTableInput)
})
}
}
return task
})
}
Putting this as an answer and not another comment in case it gets long...
It sounds like the average user's insults might fit into a single record. With the disclaimer that I know absolutely nothing about swift, this might at least be something relatively simple. Keep your customer and player keys. Before you persist the insults, turn the whole list into one big string using whatever version of join("|") swift has. When you fetch the record, do a split("|") to get your list back. (Just be a little judicious with your choice of separators, I'm only using "|" as an example, you don't want to choose something that might appear in an insult...)
There's going to be that one user with enough insults to take you over the 400kb object limit. Set a max list size constant in your code -- when you turn your lists into strings to persist them to dynamo, check the player's list length against that limit. If you exceed it, break your list into chunks of that size and use hash and range keys like ("foo", "bar"), ("foo", "bar1"), ("foo", "bar2"), etc. Yes, the first one does not have a bucket number at the end...
When you query for the data, just do a straight query first and assume you'll be in the good case (just "foo" and "bar", no other buckets). When you unpack that first list, check its length. If it's equal to your max list size constant, you know that you got a "bad" user and need to do a range query. That second one can use the hash key "foo" and the range "bar" to "bar9999". You will fetch back all those buckets with that range query. Unpack and concatenate all the lists.
This is a little gory, but it should also ultimately be straight ahead to code up. Hopefully it's still simple enough to hook into the patterns you mentioned.
What I decided to do was make a conventional dynamodb table with just one hash key, but the new hash key is a combined string of:
CustomerId + "|" + PlayerId
It is not too hard to maintain synchrony between players and insults tables because once a player is inserted into the player table, modifying the player name results in a new row being inserted. Thus, insults do not need to be modified if the player name changes. You only need to cleanup insults if a player is deleted.
This update behavior is just the way dynamodb works if you make Player name a hash key, which I did to insure they were unique.

POI - unable to create custom validation for a range of cells

I need to check if the user has entered a valid number in a cells A1:A10. In Excel i would choose the cells and then create a custom validator and set the formula to =isNumber("$A$1:$A10")
Trying do this using POI is getting me all tied in knots:
Here is what i have tried:
CellRangeAddressList addressList = new CellRangeAddressList(0, 10, 0, 0);
XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper(sheet);
DataValidationConstraint customConstraint = dvHelper.createCustomConstraint("isNumber(\"$A$0:$A$10\"");
XSSFDataValidation validation = (XSSFDataValidation)dvHelper.createValidation(customConstraint, addressList);
validation.setShowErrorBox(true);
sheet.addValidationData(validation);
When i try and open this in Excel, i get an error and Excel disables the validation
thanks in advance
-anish
CellReference crStartCell = new CellReference(startRow, column, true, true); // 0-based row and column index
CellReference crEndCell = new CellReference(endRow, column, true, true);
XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint) dvHelper.createCustomConstraint("ISNUMBER("+crStartCell.formatAsString()+":"+crEndCell.formatAsString() +")");
You can convert that excel to csv than perform your validations using SuperCSV. It would be length but more easier.

OrCriteria taking forever to execute using Tridion content delivery api

I am converting a SQL query into broker API functionality. The query basically retrieves custom meta data based on key and value filters. The issue is when I am joining two criteria using or criteria the query.executequery takes forever and the control never returns. The code that I am using is as below
PublicationCriteria pubCriteria = new PublicationCriteria(80);
//1st query
CustomMetaKeyCriteria keyCriteria1 = new CustomMetaKeyCriteria("PublicationType");
CustomMetaValueCriteria valueCriteria11 = new CustomMetaValueCriteria("Report", Criteria.Like);
CustomMetaValueCriteria valueCriteria12 = new CustomMetaValueCriteria("Video", Criteria.Like);
Criteria valueCriteria1 = CriteriaFactory.Or(valueCriteria11, valueCriteria12);
Criteria criteria1 =CriteriaFactory.And(keyCriteria1, valueCriteria1);
//2nd query
CustomMetaKeyCriteria keyCriteria2 = new CustomMetaKeyCriteria("Tags");
CustomMetaValueCriteria valueCriteria21 = new CustomMetaValueCriteria("tcm:80-20641", Criteria.Equal);
CustomMetaValueCriteria valueCriteria22 = new CustomMetaValueCriteria("tcm:80-20645", Criteria.Equal);
Criteria valueCriteria2 = CriteriaFactory.Or(valueCriteria21, valueCriteria22);
Criteria criteria2 = CriteriaFactory.And(keyCriteria2, valueCriteria2);
Criteria querycriteria = CriteriaFactory.Or(criteria1, criteria2);
Criteria finalCriteria = CriteriaFactory.And(pubCriteria, querycriteria);
Query query = new Query(criteria2);
query.SetResultFilter(new LimitFilter(10));
var n = query.ExecuteQuery();
I have tried using new orcriteria and passing the criteria as array but this also didn't work.
Couple of weeks back I tried the same, it worked for me. I have put my findings here. http://vadalis.com/custom-meta-query-from-tridionbroker-database/
Note : my broker database is very small.

LINQ TO XML Parse RSS Feed

I'm trying to parse an RSS feed using LINQ to Xml
This is the rss feed:
http://www.surfersvillage.com/rss/rss.xml
My code is as follows to try and parse
List<RSS> results = null;
XNamespace ns = "http://purl.org/rss/1.0/";
XNamespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
XDocument xdoc = XDocument.Load("http://www.surfersvillage.com/rss/rss.xml");
results = (from feed in xdoc.Descendants(rdf + "item")
orderby int.Parse(feed.Element("guid").Value) descending
let desc = feed.Element("description").Value
select new RSS
{
Title = feed.Element("title").Value,
Description = desc,
Link = feed.Element("link").Value
}).Take(10).ToList();
To test the code I've put a breakpoint in on the first line of the Linq query and tested it in the intermediate window with the following:
xdoc.Element(ns + "channel");
This works and returns an object as expect
i type in:
xdoc.Element(ns + "item");
the above worked and returned a single object but I'm looking for all the items
so i typed in..
xdoc.Elements(ns + "item");
This return nothing even though there are over 10 items, the decendants method doesnt work either and also returned null.
Could anyone give me a few pointers to where I'm going wrong? I've tried substituting the rdf in front as well for the namespace.
Thanks
You are referencing the wrong namespace. All the elements are using the default namespace rather than the rdf, so you code should be as follow:
List<RSS> results = null;
XNamespace ns = "http://purl.org/rss/1.0/";
XDocument xdoc = XDocument.Load("http://www.surfersvillage.com/rss/rss.xml");
results = (from feed in xdoc.Descendants(ns + "item")
orderby int.Parse(feed.Element(ns + "guid").Value) descending
let desc = feed.Element(ns + "description").Value
select new RSS
{
Title = feed.Element(ns + "title").Value,
Description = desc,
Link = feed.Element(ns + "link").Value
}).Take(10).ToList();

Using List of (T) with Lucene.net in vb.net

i want to use an List to store the title, path,... from Documents.
I declared the list like this:
Dim MyDocuments As New List(Of Document)
But i don't really know how to handle the list.
i want to use the list instead of an ReDim Array.
For i = 0 To results - 1 Step 1 ' forschleife zum durchlaufen der Ergebnisse
Try
MyDocuments.Add(New Document())
array_results(i, 0) = hits.Doc(i).Get("title")
array_results(i, 0) += hits.Doc(i).Get("doc_typ")
array_results(i, 1) = hits.Doc(i).Get("pfad")
'array_results(i, 2) = hits.Doc(i).Get("date_of_create") '
array_results(i, 2) = hits.Doc(i).Get("last_change")
array_results(i, 3) = CStr(hits.Score(i))
array_results(i, 4) = hits.Doc(i).Get("doc_typ")
Can I store the object Document, or do i have to create an own class??
Is there a good tutorial for using the list? (i searched, but didn't found something good)
Is the List of (T) the right data structure?
but how can i do like mylist(i) ->gettitle() or something like this?
thanks in advance!
Yes, you can store your documents in a generic List. Deciding if a List<T> is the right data structure or not depends on what you want to do with it. Maybe if you provide more information someone could come up with a better example. I don't know VB.NET so i'll do it in C#.
// i assume you're using the Document class of Lucene.NET
List<Document> documents = new List<Document>();
// add the documents to your collection
for (i = 0; i < hits.Length(); i++)
{
// each result in the list contains a Document
// which you can add to your list
documents.Add(hits.Doc(i));
}
// you can search the list for a Document following a specific rule, using lambda expressions
Document myDoc = documents.Find(d => d.Get("title") == "a value");
// you can get a document by a specific index
Document myOtherDoc = documents[0];
// you can search the list for multiple Documents following a specific rule, using lambda expressions
List<Document> myDocs = documents.FindAll(d => d.Get("doc_typ") == "a type");
More information about the List<T> can be found here: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx
More information on lambda expressions can be found here: http://msdn.microsoft.com/en-us/library/bb397687.aspx
This article on SO shows how to use lambdas to search a List<T>

Resources