I am running the below code
IQueryable<customSearchResultItem> query = context.GetQueryable<customSearchResultItem>().Where(CombinPredicates);
var hits = query.GetResults().Hits;
Sitecore.Diagnostics.Log.Info("search query hits:" + hits.Count(), context.Index);
foreach (var item in hits)
{
string builder = string.Empty;
try
{
string docitemid = item.Document.ItemId.ToString();
Sitecore.Diagnostics.Log.Info("document itemid:" + docitemid, item);
Item resultItem = item.Document.GetItem();
}
catch (Exception ex)
{
Sitecore.Diagnostics.Log.Info("search error going through hits:" + ex.Message, ex);
builder += item.Document.ItemId.ToString() + "\n";
continue;
}
}
the above actually returns results in the "hits" variable. However, I was getting zero results rendered out to the front end of the site. the code above is my debugging code to see what is going on.
With the hits I get back, I just loop through, nothing more.
When performing the loop and writing to logs, the below 2 lines actually return as expected, a valid Sitecore itemID
string docitemid = item.Document.ItemId.ToString();
Sitecore.Diagnostics.Log.Info("document itemid:" + docitemid, item);
However, the following line
Item resultItem = item.Document.GetItem();
returns as NULL
why would this be?
to complicate further, this code actual works in a one environment but not another, hence the reason for the debugging.
Also, the Sitecore item is present it both master and web databases and in the SOLR index
I've been having a similar problem where I was searching in the Prod (web) environment items indexed via the Stage Sitecore instance. I believe the GetItem() method uses the database, item id, language and version of the search result item, which are parsed from the _uniqueid that looks something like this:
...
"_uniqueid":"sitecore://stage/{d31b5802-c123-4690-86ff-8566dc896814}?lang=en&ver=1&ndx=my_site_index"
...
So in my case it wasn't finding the Sitecore item, because it was looking in the stage database, where as my Sitecore.Context.Database was the web one.
I know this answer is way late :-), but I hope it helps someone else who happens to run into this issue.
Related
I recently upgraded from sqlite-jdbc-3.7.2.jar to sqlite-jdbc-3.26.0.jar. I observed that the insert query in my code are failing with “java.sql.SQLException: Values not bound to statement” exception.
Below is the piece of code which works fine for previous version of sqlite :
String sqlStatement = "INSERT INTO table_name(id,name,type,author,size) VALUES (?,?,?,?,?)";
try
{
Connection conn = this.connect(<name>);
PreparedStatement pstmt = conn.prepareStatement(sqlStatement))
{
pstmt.setInt(1, rs.getInt(<value>));
pstmt.setString(2, rs.getString(<value>));
pstmt.setInt(3, rs.getInt(<value>));
if (somecondition)
{
pstmt.setString(4, rs.getString(<Value>));
pstmt.setInt(5, rs.getInt(<value>));
}
pstmt.executeUpdate();
}
}
catch(Exception e)
{
//handling of exception goes here
}
I have read the release notes https://www.sqlite.org/changes.html and checked that as a part of Query planner enhancements, few things were changed (The query planner examines the values of bound parameters to help determine if a partial index is usable.
).
But I am still not clear what was the enhancement and how it is affecting my code.
Also can someone guide me on how to fix the above code?
Thanks,
Ketaki
In the above program, the insert query was expecting 5 values to be populated by user.
However, if(somecondition) is not satisfied then values for 4th and 5th were not getting inserted in query. This was the issue since sqlite-jdbc-3.26.0 expects all values to be populated before executing the query. In the fix, I ensured that all values are populated even if "somecondition" is false by inserting else block.
Fix :
if (somecondition)
{
pstmt.setString(4, rs.getString(<Value>));
pstmt.setInt(5, rs.getInt(<value>));
}
else
{
pstmt.setString(4, rs.getString(<default-value>));
pstmt.setInt(5, rs.getInt(<defaul`enter code here`t-value>));
}
I tried adding a new column to an existing search index but it is throwing an error, the error as stated below:-
Field docname is present 0 times; expected 1
java.lang.IllegalArgumentException: Field docname is present 0 times; expected 1
I can see that the new column has been added to the search index but cannot retrieve the index.
By my observation i can see that the existing records in the index dont have the new column data and hence it is giving a this error, but the new records will be having this column values. Can anyone help me with this.
Upon having this problem myself today, I searched a bit in the documentation. It was a rather frustrating error as it didn't actually pin point where the problem was in my code.
It appears that when you use getOnlyField("something") on a Document (in this case on one of many returned from a search query), if that field does not actually exist yet in that specific document it throws the java.lang.IllegalArgumentException.
Because that can often be the case when you update an index with new columns, I'm using something like this to get around it:
public static Long getNumberField(ScoredDocument d, String name, Long defaultValue) {
try {
return d.getOnlyField(name).getNumber().longValue();
} catch (IllegalArgumentException e) {
return defaultValue;
}
}
Which is called in the search results code:
Long numberValue = SearchUtils.getNumberField(scoredDocument, "featuredOrder", -1L)
This allows me to catch that error and return a default value when it doesn't exist.
You can find the documentation here:
https://cloud.google.com/appengine/docs/java/javadoc/com/google/appengine/api/search/Document.html#getOnlyField-java.lang.String-
I am trying to write an app engine application for my university. What I am trying to achieve right now, is to create a method which takes in a Course name, and returns a list of all the CourseYears (think of that as being like a link table e.g. if Maths is the course, and it has Year 1, year 2 and Year 3; MathsYear1, MathsYear2 and MathsYear3 would be the names of the CourseYears).
This is the code for the module (WARING: super dirty code below!):
#ApiMethod(name = "courseYears")
public ArrayList<CourseYear> courseYears(#Named("name") String name){
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Query.Filter keyFilter = new Query.FilterPredicate("name", Query.FilterOperator.EQUAL, name);
Query query = new Query("Course").setFilter(keyFilter);
PreparedQuery preparedQuery = datastore.prepare(query);
List<Entity> resultList = preparedQuery.asList(FetchOptions.Builder.withLimit(1));
Course course = ofy().load().type(Course.class).id(resultList.get(0).getKey().getId()).now();
ArrayList<String> courseYearNames = course.getAllCourseYearNames();
System.out.println(course.getName());
ArrayList<CourseYear> courseYears = new ArrayList<CourseYear>();
for(String courseYearName: courseYearNames){
Query.Filter courseNameFilter = new Query.FilterPredicate("name", Query.FilterOperator.EQUAL, courseYearName);
Query query2 = new Query("CourseYear").setFilter(courseNameFilter);
List<Entity> resL = preparedQuery.asList(FetchOptions.Builder.withLimit(1));
System.out.println("test");
CourseYear courseYear = ofy().load().type(CourseYear.class).id(resL.get(0).getKey().getId()).now();
courseYears.add(courseYear);
}
return courseYears;
}
It basically takes a Course name in, applies a filter on all courses to get the corresponding Course object, and then calls getAllCourseYearNames() on the course to get an array list containing all its CourseYears' names. (I would have loved to do this using Keys, but parameterised Objectify keys don't seem to be supported in this version of App Engine).
I then try and get the CourseYears by looping through the arraylist of names and applying the filter for each name. I print "test" each time to see how many times it is looping. Like I said, a super dirty way of doing it.
When I try passing a few course names as a parameters, it loops the correct number of times only once or twice, and after that does not loop at all (doesn't print "test"). I could understand if it never looped, but not doing it correctly once or twice and then never again. It doesn't successfully return a list of CourseYears when it does work, but rather the relevant number of NULLs - I don't know if this is relevant. I believe it successfully retrieves the course every time, as I print the name of the course after loading and it never fails to do this.
If anyone has ANY suggestions for why this may be happening, I would be incredibly grateful to hear them!
Thanks
query2 is never used in your code. You reuse preparedQuery from your previous query, which runs on a different entity kind.
I have a problem with the android cursor looping twice, even though I know there is only one value returned in the cursor.getCount().
I'm using the following in the DBAdapter:
public Cursor getAllSubDetailsFromObsTable() {
Cursor c = mDb
.rawQuery(
"SELECT DISTINCT sub.sub_id, sub.complete, mobileobs.date, mobileobs.location, mobileobs.grid_ref, "
+ "mobileobs.time, mobileobs.protocol_id, mobileobs.endtime FROM sub, mobileobs "
+ "WHERE sub.sub_id = mobileobs.sub_id",
null);
return c;
}
Then I call this within my worker class with:
db.open();
Cursor c = db.getAllSubDetailsFromObsTable();
while (c.moveToNext()) {
String sub_id = c.getString(0);
//Rest of real code <snipped>
myArrayList.add(sub_id);
}
c.close();
db.close();
However, when I look at the contents of myArrayList, it has two identical values of sub_id. I have tried mucking about with c.moveToFirst() etc. etc. but I still get two values in the arrayList even though c.getCount() = 1!
finally nailed this. It was to do with class variables and method variables. I had a class variable that was being populated by a method within onCreate that was also being called within onResume. Solution was to move the variable into the method. Stupid bug, easy to fix, difficult (for me) to find.
I've got this code (Java, GAE):
// Much earlier:
playerKey = KeyFactory.keyToString(somePlayer.key);
// Then, later...
PersistenceManager pm = assassin.PMF.get().getPersistenceManager();
Key targetKey = KeyFactory.stringToKey(playerKey);
Query query = pm.newQuery(Player.class);
query.setFilter("__key__ == keyParam");
query.declareParameters("com.google.appengine.api.datastore.Key keyParam");
List<Player> players = (List<Player>) query.execute(targetKey); // <-- line 200
which generates this error:
javax.jdo.JDOFatalUserException: Unexpected expression type while parsing query. Are you certain that a field named __key__ exists on your object?
at org.datanucleus.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:354)
at org.datanucleus.jdo.JDOQuery.execute(JDOQuery.java:252)
at myapp.Player.validPlayerWithKey(Player.java:200)
// [etc., snip]
But I'm not sure what it wants. I'm trying to search on the JDO id field, which I I thought I read had the special name __key__, in the documentation.
I've tried it with both
query.setFilter("__key__ == keyParam");
and
query.setFilter("ID == keyParam");
with the same results. So, what am I doing wrong? Or, more importantly, how do I do it correctly?
Thanks!
Edit: For completeness's sake, here is the final, working code (based on Gordon's answer, which I have accepted as correct):
Player result = null;
if (playerKey == null)
{
log.log(Level.WARNING, "Tried to find player with null key.");
}
else
{
PersistenceManager pm = assassin.PMF.get().getPersistenceManager();
try {
result = (Player) pm.getObjectById(Player.class, playerKey);
} catch (javax.jdo.JDOObjectNotFoundException notFound) {
// Player not found; we will return null.
result = null;
}
pm.close();
}
return result;
If your objective is to get an object by key, then you should use the PersistenceManager's getObjectByID() method. More details here.
As an aside, trying to construct a query to get something by it's key is something you shouldn't need to do. Although this is how you would work with an SQL database, the Google Data Store does things differently, and this is one of those cases where rather than go through the trouble of constructing a query, Google App Engine lets you get what you want directly. After all, you should only have one entity in the database with a particular key, so there's nothing in the rest of the machinery of a GQL query that you need in this case, hence it can all be skipped for efficiency.
I would recommend you to use the JPA ( http://code.google.com/appengine/docs/java/datastore/usingjpa.html ) to access your data in GAE, it has the very important advantage that you can use the widely known and documented JPA standard (and its JPAQL querying language) to do this kind of things, in portable way (if you stick to the JPA standard, your code will work for GAE, for Hibernate or with EclipseLink without modification)