We are experiencing an issue where a FullTextSqlQuery is only returning the default 100 results whenever certain criteria are added in the WHERE clause. We are setting the RowLimit to int.MaxValue, and when a wide-open search is done, we are receiving the max results. It's only an issue when tacking-on CONTAINS clauses. Has anyone else seen this issue? I wasn't able to dig up anything on Google/Bing.
FullTextSqlQuery kRequest = new FullTextSqlQuery(ServerContext.Current);
kRequest.KeywordInclusion = KeywordInclusion.AnyKeyword;
kRequest.ResultTypes = ResultType.RelevantResults;
kRequest.TrimDuplicates = false;
kRequest.RowLimit = int.MaxValue;
kRequest.Timeout = 120000;
ResultTableCollection resultTbls = kRequest.Execute();
Query Code:
string query = "SELECT Title, Path, Facility, OwnerDepartment,
FacilityActiveDate, FacilityInactiveDate, ScheduledReviewDate, DocID,
Version FROM SCOPE() WHERE ";
query += "Path like '%" + site.Url + "%'";
// when it hits the else statement is an example of when it will only
// return 100 results
if (FacilitySelectedIndex == 1)
{
query += " AND Facility IS NOT NULL";
}
else
{
query += " AND CONTAINS(Facility, '\"*" + FacilityShortName.Trim() + "*\"')";
queryText.Add("Facility=" + FacilityShortName);
}
}
If I recall correctly, the RowLimit max value is actually less than int.MaxValue, only it won't tell you that. Try setting the RowLimit to some arbitrary large number that is still smaller than int.MaxValue, such as 99999
Related
I'm trying to create a namedquery with a set that changes 2 fields. Below is what I tried, which isn't working. It worked fine until I added the ae.endTime and the setParameter. Can you not SET multiple things in one query?
#NamedQuery(name = AttEnt.JQL.MARK_INCOMPLETE,
query = "UPDATE AttEnt ae"
+ " SET ae.result ="
+ " Result.INCOMPLETE,"
+ " ae.endTime = :now"
+ " WHERE ae.result IS NULL")
Below is where I'm calling the query.
final EntityManager em = emf.createEntityManager();
// Mark things with no result as incomplete and endTime to current time
em.getTransaction().begin();
final Query upAtt = em.createNamedQuery(
AttEnt.JQL.MARK_INCOMPLETE);
updateAttempts.setParameter("now", (new Date()).getTime());
upAtt.executeUpdate();
em.getTransaction().commit();
Depending on how you have mapped your endTime field, you should use an overloaded variation of the setParameter method, which add the datetime information. For example:
updateAttempts.setParameter("now", (new Date()).getTime(), TemporalType.TIME);
Here more on Temporal Types.
I'm trying to get a field to update with each line item on the invoice (without over writing what is already there), using a Query Expression to get the data that needs to be used to update the field.
So far I've been able to get this to work just fine when only 1 line item is present. But whenever I test this against multiple line items I get the " The given key was not present in the dictionary." error.
Any help or nudge in the right direction?
QueryExpression lineitem = new QueryExpression("invoicedetail");
lineitem.ColumnSet = new ColumnSet("quantity", "productid", "description");
lineitem.Criteria.AddCondition("invoiceid", ConditionOperator.Equal, invoiceid);
EntityCollection results = server.RetrieveMultiple(lineitem);
Invoice.Attributes["aspb_bookmarksandk12educational"] = "Purchases";
Invoice.Attributes["aspb_bookmarksandk12educational"] += "\n";
Invoice.Attributes["aspb_bookmarksandk12educational"] += "Product" + " " + "Quantity";
Invoice.Attributes["aspb_bookmarksandk12educational"] += "\n";
foreach (var a in results.Entities)
{
string name = a.Attributes["description"].ToString();
string quantity = a.Attributes["quantity"].ToString();
Invoice.Attributes["aspb_bookmarksandk12educational"] += " " + name + " ";
Invoice.Attributes["aspb_bookmarksandk12educational"] += quantity;
Invoice.Attributes["aspb_bookmarksandk12educational"] += "\n";
}
"The given key was not present in the dictionary."
Suggests the problem lies in the way you are trying to access attribute values and not with the multiple entities returned. When you try get an attribute value, try to check if the attribute exists before reading the value like so:
if (a.Attributes.ContainsKey("description"))
{
var name = a.Attributes["description"] as string;
}
Or even better use the SDK extension methods to help do the check and return a default value for you like so:
var name = a.GetAttributeValue<string>("description");
var quantity = a.GetAttributeValue<decimal>("quantity");
I have a query to get photos according to values in a pivot table, that stores the relation of "pics" and "tags":
#photos
$q = PicTag::select(DB::raw('distinct(pics.id)'),
'pics.url',
'pics.titel',
'pics.hits',
'pics.created_at',
'users.username',
'users.displayname')
->leftJoin('pics', 'pics.id', '=', 'pic_tag.pic_id')
->leftJoin('users','users.id','=','pics.user_id')
->whereIn('pic_tag.tag_id', $tagids);
if($cat)
$q->where('typ',$cat);
if($year)
$q->where('jahrprod',$year);
$pics = $q->orderBy('pics.id','desc')
->paginate(30);
The problem is, when for a certain photo multiple (same) tags are stored like "Tag", "tag" and "tAG". Then the same photo would be shown 3 times in my gallery. That is why I use the distinct in the query.
Then the gallery is ok, but $pics->total() does not show "87 photos" but for example "90 photos", because the distinct is not used in the pagination. In laravel 4, I used groupBy('pics.id'), but this did not seem to be the fastest query and with laravel 5 it gives me a total() count result of 1.
How could I get the right total() value?
I know it's an old subject but it could help some other people.
I faced the same problem and the only good solution (low memory cost) I found was to do the request in two times:
$ids = DB::table('foo')
->selectRaw('foo.id')
->distinct()
->pluck('foo.id');
$results = $query = DB::table('foo')
->selectRaw('foo.id')
->whereIn('foo.id', $ids)
->paginate();
I tried this with 100k results, and had no problem at all.
Laravel has issue in paginate of complex queries. so you should handle them manually . In laravel 5 I did it in 2 steps :
Step 1: repository method :
public function getByPage($page = 1, $limit = 10 , $provinceId , $cityId , $expertiseId)
{
$array = ['users.deleted' => false];
$array["users.approved"] = true;
$array["users.is_confirmed"] = true;
if($provinceId)
$array["users.province_FK"] = $provinceId;
if($cityId)
$array["users.city_FK"] = $cityId;
if($expertiseId)
$array["ONJNCT_USERS_EXPERTISE.expertise_FK"] = $expertiseId;
$results = new \stdClass();
$results->page = $page;
$results->limit = $limit;
$results->totalItems = 0;
$results->items = array();
$users= DB::table('users')
->distinct()
->select('users.*','ONDEGREES.name as drgree_name')
->join('ONJNCT_USERS_EXPERTISE', 'users.id', '=', 'ONJNCT_USERS_EXPERTISE.user_FK')
->join('ONDEGREES', 'users.degree_FK', '=', 'ONDEGREES.id')
->where($array)
->skip($limit * ($page - 1))->take($limit)->get();
//$users = $usersQuery>skip($limit * ($page - 1))->take($limit)->get();
$usersCount= DB::table('users')
->select('users.*','ONDEGREES.name as drgree_name')
->join('ONJNCT_USERS_EXPERTISE', 'users.id', '=', 'ONJNCT_USERS_EXPERTISE.user_FK')
->join('ONDEGREES', 'users.degree_FK', '=', 'ONDEGREES.id')
->where($array)
->count(DB::raw('DISTINCT users.id'));
$results->totalItems = $usersCount;
$results->items = $users;
return $results;
}
Step 2:
In my Search Controller :
function search($provinceId , $cityId , $expertiseId){
$page = Input::get('page', 1);
$data = $this->userService->getByPage($page, 1 , $provinceId ,$cityId , $expertiseId);
$users = new LengthAwarePaginator($data->items, $data->totalItems, 1 , Paginator::resolveCurrentPage(),['path' => Paginator::resolveCurrentPath()]);
return View::make('guest.search.searchResult')->with('users' ,$users);
}
It worked for me well!
Recently I've started using Apache CMIS and read the official documentation and examples. I haven't noticed anything about paging query results.
There is an example showing how to list folder items, setting maxItemsPerPage using operationContext, but it seems that operationContext can be used inside getChilder method:
int maxItemsPerPage = 5;
int skipCount = 10;
CmisObject object = session.getObject(session.createObjectId(folderId));
Folder folder = (Folder) object;
OperationContext operationContext = session.createOperationContext();
operationContext.setMaxItemsPerPage(maxItemsPerPage);
ItemIterable<CmisObject> children = folder.getChildren(operationContext);
ItemIterable<CmisObject> page = children.skipTo(skipCount).getPage();
This is ok when it comes to listing u folder. But my case is about getting results from custom search query. The basic approach is:
String myType = "my:documentType";
ObjectType type = session.getTypeDefinition(myType);
PropertyDefinition<?> objectIdPropDef = type.getPropertyDefinitions().get(PropertyIds.OBJECT_ID);
String objectIdQueryName = objectIdPropDef.getQueryName();
String queryString = "SELECT " + objectIdQueryName + " FROM " + type.getQueryName();
ItemIterable<QueryResult> results = session.query(queryString, false);
for (QueryResult qResult : results) {
String objectId = qResult.getPropertyValueByQueryName(objectIdQueryName);
Document doc = (Document) session.getObject(session.createObjectId(objectId));
}
This approach will retrieve all documents in a queryResult, but I would like to include startIndex and limit. The idea would be to type something like this:
ItemIterable<QueryResult> results = session.query(queryString, false).skipTo(startIndex).getPage(limit);
I'm not sure about this part: getPage(limit). Is this right approach for paging? Also I would like to retrieve Total Number of Items, so I could know how to set up the max items in grid where my items will be shown. There is a method, but something strange is written in docs, like sometimes the repository can't be aware of max items. This is that method:
results.getTotalNumItems();
I have tried something like:
SELECT COUNT(*)...
but that didn't do the trick :)
Please, could you give me some advice how to do a proper paging from a query result?
Thanks in advance.
Query returns the same ItemIterable that getChildren returns, so you can page a result set returned by a query just like you can page a result set returned by getChildren.
Suppose you have a result page that shows 20 items on the page. Consider this snippet which I am running in the Groovy Console in the OpenCMIS Workbench against a folder with 149 files named testN.txt:
int PAGE_NUM = 1
int PAGE_SIZE = 20
String queryString = "SELECT cmis:name FROM cmis:document where cmis:name like 'test%.txt'"
ItemIterable<QueryResult> results = session.query(queryString, false, operationContext).skipTo(PAGE_NUM * PAGE_SIZE).getPage(PAGE_SIZE)
println "Total items:" + results.getTotalNumItems()
for (QueryResult result : results) {
println result.getPropertyValueByQueryName("cmis:name")
}
println results.getHasMoreItems()
When you run it with PAGE_NUM = 1, you'll get 20 results and the last println statement will return true. Also note that the first println will print 149, the total number of documents that match the search query, but as you point out, not all servers know how to return that.
If you re-run this with PAGE_NUM = 7, you'll get 9 results and the last println returns false because you are at the end of the list.
If you want to see a working search page that leverages OpenCMIS and plain servlets and JSP pages, take a look at the SearchServlet class in The Blend, a sample web app that comes with the book CMIS & Apache Chemistry in Action.
Having a problem with the code below only adds the latest value in the TestTaxonomyControl.Text to the metadata column. ( multiple values is turned on )
TaxonomyFieldValueCollection values = new TaxonomyFieldValueCollection(String.Empty);
values.PopulateFromLabelGuidPairs(TestTaxonomyControl.Text);
TaxonomyField entKeyword = (TaxonomyField)item.Fields["Metadata"];
foreach (TaxonomyFieldValue value in values)
{
TaxonomyFieldValue term = new TaxonomyFieldValue("1;#" + value.Label + "|" + value.TermGuid);
entKeyword.SetFieldValue(item, term);
}
item.Update();
I'd say you only need something like:
TaxonomyFieldValueCollection values = new TaxonomyFieldValueCollection(String.Empty);
values.PopulateFromLabelGuidPairs(TestTaxonomyControl.Text);
item["Metadata"] = values;
item.Update();