Solr scoring based on subdocument (parent blockjoin) - join

I have the following structure of ... lets say products in a store. The Products have a rating. Then users can, additionally, rate the product (on their own). Lets say 300k Products plus 50k user-ratings (to each product)
Question 1: Are Subdocuments the right choice? I am adding everything with SolrJ, I did not find any other suitable method of doing that.
For sake of an example, you could copy and paste the following code to your collection:
<add>
<doc>
<field name="id">1</field>
<field name="title" >Product Title LOLO</field>
<field name="content_type" >parent</field>
<field name="rating_f" >7</field>
<doc>
<field name="id">1</field>
<field name="user_id_s" >123</field>
<field name="userrating_f" >1.2</field>
</doc>
</doc>
<doc>
<field name="id">2</field>
<field name="title" >Product Title LULU</field>
<field name="content_type" >parent</field>
<field name="rating_f" >2</field>
</doc>
<doc>
<field name="id">3</field>
<field name="title" >Product Title LALA</field>
<field name="content_type" >parent</field>
<field name="rating_f" >1.4</field>
<doc>
<field name="id">1</field>
<field name="user_id_s" >123</field>
<field name="userrating_f" >5</field>
</doc>
</doc>
</add>
Question 2 (The Important one): How can I query this index now, so that the documents are scored with a boost on the user-rating first (if one exists) and then by the product rating (and then by other fields, like the creation date, views, buys, ...)? Is that even possible?
I was looking into something like that:
{!parent which="content_type:parent"}(user_id_s:123 AND _val_:userrating_f)^2.0 _val_:rating_f^2.0 *:*
That should return the documents in this order (ids): 3, 1, 2
But instead it returns:
{
"responseHeader": {
"status": 500,
"QTime": 1,
"params": {
"indent": "true",
"q": "{!parent which=\"content_type:parent\"}(user_id_s:123 AND _val_:userrating_f)^2.0 _val_:rating_f^2.0 *:*",
"_": "1421996862814",
"wt": "json"
}
},
"error": {
"msg": "child query must only match non-parent docs, but parent docID=3 matched childScorer=class org.apache.lucene.search.DisjunctionSumScorer",
"trace": "java.lang.IllegalStateException: child query must only match non-parent docs, but parent docID=3 matched childScorer=class org.apache.lucene.search.DisjunctionSumScorer\n\tat org.apache.lucene.search.join.ToParentBlockJoinQuery$BlockJoinScorer.nextDoc(ToParentBlockJoinQuery.java:344)\n\tat org.apache.lucene.search.Weight$DefaultBulkScorer.scoreAll(Weight.java:192)\n\tat org.apache.lucene.search.Weight$DefaultBulkScorer.score(Weight.java:163)\n\tat org.apache.lucene.search.BulkScorer.score(BulkScorer.java:35)\n\tat org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:621)\n\tat org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:297)\n\tat org.apache.solr.search.SolrIndexSearcher.buildAndRunCollectorChain(SolrIndexSearcher.java:209)\n\tat org.apache.solr.search.SolrIndexSearcher.getDocListNC(SolrIndexSearcher.java:1619)\n\tat org.apache.solr.search.SolrIndexSearcher.getDocListC(SolrIndexSearcher.java:1433)\n\tat org.apache.solr.search.SolrIndexSearcher.search(SolrIndexSearcher.java:514)\n\tat org.apache.solr.handler.component.QueryComponent.process(QueryComponent.java:485)\n\tat org.apache.solr.handler.component.SearchHandler.handleRequestBody(SearchHandler.java:218)\n\tat org.apache.solr.handler.RequestHandlerBase.handleRequest(RequestHandlerBase.java:135)\n\tat org.apache.solr.core.SolrCore.execute(SolrCore.java:1967)\n\tat org.apache.solr.servlet.SolrDispatchFilter.execute(SolrDispatchFilter.java:777)\n\tat org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:418)\n\tat org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:207)\n\tat org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1419)\n\tat org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:455)\n\tat org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)\n\tat org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)\n\tat org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)\n\tat org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1075)\n\tat org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:384)\n\tat org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)\n\tat org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1009)\n\tat org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)\n\tat org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255)\n\tat org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:154)\n\tat org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)\n\tat org.eclipse.jetty.server.Server.handle(Server.java:368)\n\tat org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)\n\tat org.eclipse.jetty.server.BlockingHttpConnection.handleRequest(BlockingHttpConnection.java:53)\n\tat org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:942)\n\tat org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1004)\n\tat org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:640)\n\tat org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)\n\tat org.eclipse.jetty.server.BlockingHttpConnection.handle(BlockingHttpConnection.java:72)\n\tat org.eclipse.jetty.server.bio.SocketConnector$ConnectorEndPoint.run(SocketConnector.java:264)\n\tat org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)\n\tat org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)\n\tat java.lang.Thread.run(Thread.java:745)\n",
"code": 500
}
}

there is SolrInputDocument.getChildrenDocs() collection or so. use it.
to propagate score from children query to parent ones you need https://issues.apache.org/jira/browse/SOLR-5882
the problem is that functional queries matches every docs, thus it violates orthogonality and causes the exception. intersect children query with +content_type:child

Related

SQL Server 2008 R2 Parsing XML Data

I am having some issues pulling data I need from a database running SQL Server 2008 R2. The column that I am trying to pull data out of is in XML and I am having trouble parsing it. I tried looking up examples online of how to do this, but I seem to be struggling. In fact, some of the functions I saw do not seem to work in my queries, like the .nodes() or .value() function. Plus, the examples I see being used are different then how my data is stored. Here is an example of one of the XML records:
<?xml version="1.0" encoding="utf-8"?>
<view name="Terminate" className="Employee" viewName="Employee" dataArea="lmghr" executor="REMOTE_GRID" layoutType="1" isDisplayOnly="false">
<action name="Terminate" type="UPDATE" isRequestAction="true" scheduleType="FOREGROUND" scheduleChoice="FOREGROUND"></action>
<fields>
<field name="HROrganization" id="HROrganization"><![CDATA[ORG#]]></field>
<field name="Employee" id="Employee"><![CDATA[EMPLOYEE#]]></field>
<field name="RequestedBy" id="RequestedBy"><![CDATA[REQUESTER NAME]]></field>
<field name="RequesterEmail" id="RequesterEmail"><![CDATA[requesteremail#email.org]]></field>
<field name="EmployeeName" id="EmployeeName"><![CDATA[EMPLOYEE NAME]]></field>
<field name="TerminationDate" id="TerminationDate"><![CDATA[20180109]]></field>
<field name="LastDatePaid" id="LastDatePaid"><![CDATA[20180108]]></field>
<field name="RelationshipStatus" id="RelationshipStatus"> <![CDATA[TERMINATED]]></field>
<field name="TerminationNoticeDate" id="TerminationNoticeDate"><![CDATA[20180109]]></field>
<field name="ActionRequest" id="ActionRequest"><![CDATA[0160bfd1-c806-0000-003d-21e6538f85a8]]></field>
<field name="Employee_reason_code" id="Employee_reason_code"><![CDATA[TI- POORATTEND]]></field>
<field name="Employee_action_comment" id="Employee_action_comment"><![CDATA[]]></field>
<field name="Employee_effective_date" id="Employee_effective_date"><![CDATA[20180109]]></field>
</fields>
<views></views>
</view>
Is anyone able to help me out or at least point me in the right direction?
Thanks.
Edit: I think the reason I was having issues with .node and .value is because the column is a nvarchar datatype, not XML. When I cast the column as XML it no longer has an issue with the code before I run it, but then when I do I get
Msg 9402, Level 16, State 1, Line 1
XML parsing: line 1, character 38, unable to switch the encoding
Code:
SELECT CAST(XMLcol AS XML).value('(view/fields/field/node())[1]', 'nvarchar(max)') AS HRORG
FROM MyTable
EDIT 2: The beginning of the XML statement was causing errors when I ran it so I did:
SELECT
CAST(REPLACE(XMLCol, '<?xml version="1.0" encoding="utf-8"?>', '') AS XML).value('(view/fields/field/node())[1]', 'nvarchar(max)') AS XMLDATA
FROM
XMLTABLE
this returns a value of ORG#, but how do I show the other fields in the query results?
SELECT XMLDATA.value('(view/fields/field/node())[1]', 'nvarchar(max)') AS Col1
,XMLDATA.value('(view/fields/field/node())[2]', 'nvarchar(max)') AS Col2
,XMLDATA.value('(view/fields/field/node())[3]', 'nvarchar(max)') AS Col3
,XMLDATA.value('(view/fields/field/node())[4]', 'nvarchar(max)') AS Col4
,XMLDATA.value('(view/fields/field/node())[5]', 'nvarchar(max)') AS Col5
,XMLDATA.value('(view/fields/field/node())[6]', 'nvarchar(max)') AS Col6
FROM (SELECT CONVERT(XML, REPLACE(XMLDATA, '<?xml version="1.0" encoding="utf-8"?>', '')) AS XMLDATA
FROM MyTable) A

Is the mapping in sequential order in Dozer?

I have Dozer mapping as follows
<mapping>
<class-a>Class1</class-a>
<class-b>Class2</class-b>
<field> <a>C1.field1</a> <b>C2.field1</b> </field>
<field custom-converter="converterField2"> <a>C1.field2</a> <b>C2.field2</b> </field>
<field> <a custom-converter="converterField3"> C1.field3</a> <b>C2.field3</b> </field>
<field> <a>C1.field4</a> <b>C2.field4</b> </field>
</mapping>
I have four mappings mapping file. Does the Dozer maps in order like field1 is mapped first, followed by field2 and then by field3?
Or will do map in any order?
Yes, the mapping happens in order. The field names are fetched from the files by Reflection and added to Lists. These lists are then iterated over and the values mapped one by one.
Specifically, the names are fetched here and the mapping starts here.

field rules: serverdefault vs. readonly

I want to use a custom datetime attribute to track, when an item entered a given state for the first time (serverdefault:clock).
To avoid later manipulation, this custom field at the same time should be set to readonly for everyone.
It seems however that in all combinations I come up with the "readonly" takes precedence and immediat es ly blocks the "serverdefault" that seems to be executed with the rights of the user iniziating tha transition.
For e.g. "created date" however the behavior seems possible for the system itself ...
Is there a way to achieve the same behavior for custom fields?
You can define your field like this:
<FIELD name="Custom Date" refname="My.CustomDate" type="DateTime">
<WHENNOTCHANGED field="System.State">
<READONLY />
</WHENNOTCHANGED>
</FIELD>
and then add this XML to the TRANSITION node for the given state:
<TRANSITION from="Resolved" to="Closed">
<FIELDS>
<FIELD refname="My.CustomDate">
<SERVERDEFAULT from="clock" />
</FIELD>
</FIELDS>
</TRANSITION>

Assigning Default value in DateTime field in TFS

Is it possible to assign DEFAULT rule for DateTime Field while adding a Work Item in TFS? But not using CLOCK value. Giving some Default Date.
Yes, you can do this by hardcoding the value in the Work Item Type Definition. In the appropriate TRANSITION element under the FIELDS\FIELD element for that field, instead of using ServerDefault and clock which you have probably seen like this:
<FIELD refname="Microsoft.VSTS.Common.ActivatedDate">
<SERVERDEFAULT from="clock" />
</FIELD>
try doing this:
<FIELD refname="Microsoft.VSTS.Common.ActivatedDate">
<COPY from"value" value="01-Feb-2014" />
</FIELD>
It is possible, try this:
<FIELD name="Custom Date" refname="Custom.Date" type="DateTime">
<DEFAULT from="value" value="2100-01-01" />
</FIELD>
The date that will be displayed is a day before of whatever date you're setting.

how to set height of textbox in tree view from xml in openerp?

<record id="view_tr_mail_template_tree" model="ir.ui.view">
<field name="name">view_tr_mail_template_tree</field>
<field name="model">tr.mail.template</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Mail template">
<field name="category" select="1" />
<field name="tr_lang" select="1" />
<field name="mail_desc" height="250"/>
</tree>
</field>
</record>
the above code shows tree view.my requirement is ,if i av a text of 50 to 80 lines in form view,in tree view the whole text as to be concatenated to 3 or 4 lines and display. giving height="250" in tree view does not work.....
I know it's an old question, but in case someone's looking for the answer: here's what you'll have to do.
Step 1. Create the directory structure static/src/css in your module's root directory and create a new css file in that directory (eg. my_styles.css)
Step 2. Create the following style definitions in the css file:
.text_high {
height: 250px;
}
.text_high textarea {
height: 100%;
}
..and adjust the height to your needs. In my case I found out that 45px was perfect for me (~2 rows).
Step 3. Add this in your __openerp__.py:
"css": ["static/src/css/my_styles.css"],
Step 4. Add the class attribute to your text field tag like this:
<field name="mail_desc" class="text_high"/>
Step 5. Update your module and you're all set.

Resources