Apache Solr - index data - apache

I have two tables: tableA and tableB. There is one to many relationship between this tables. One row in tableA corresponds to multiple rows in tableB. I have query:
select aa.id, aa.first_name, aa.last_name, bb.address_home, bb.address_coresp from testA aa, testB bb where aa.id = bb.testA_fk;
which returns many rows - 3 for example:
1 John Terry HOME 1 CORESP_1
1 John Terry HOME 11 CORESP_11
1 John Terry HOME 111 CORESP_111
When I insert this query into solr`s data-config.xml file and index data, then the result is:
{"address_home": ["HOME 111"],
"address_coresp": ["CORESP_111"],
"id": "1",
"LAST_NAME": "Terry",
"FIRST_NAME": "John",
"_version_": 1513906493806608400
}
There is only one address result instead of three.
Fragment of my data-config.xml:
<document name="testDoc">
<entity name="testA" query="select aa.id, aa.first_name, aa.last_name, bb.address_home, bb.address_coresp from testA aa, testB bb where aa.id = bb.testA_fk">
<field column="id" name="id" />
<field column="first_name" name="first_name" />
<field column="last_name" name="last_name" />
<field column="address_home" name="address_home" />
<field column="address_coresp" name="address_coresp" />
</entity>
</document>
and in schema.xml I have multiValued set to true:
<field name="address_home" type="text_general" indexed="true" stored="true" multiValued="true" /><field name="address_coresp" type="text_general" indexed="true" stored="true" multiValued="true" />
I know that the solution for my problem is nested entity element:
<entity name="testA" query="select * from testA">
field definitions...
<entity name="testB" query="select * from testB where testB.a_id = '${testA.id}'">
field definitions...
</entity>
</entity
, but is there an option to do that in one query. I want to achieve this result:
{"id": "1",
"LAST_NAME": "Terry",
"FIRST_NAME": "John",
"address_home": ["HOME 1","HOME 11","HOME 111"],
"address_coresp": ["CORESP_1","CORESP_11","CORESP_111"],
"_version_": 1513905361988354000
}
Thanks in advance

Check your schema.xml for the value of uniqueKey, I suspect it is set to "id":
<uniqueKey>id</uniqueKey>
Therefore, each subsequent record with an id of "1" is overwriting the last, resulting in only the last record with an id of "1" being retained in the index.
If you need to be able to update the documents in Solr when the data changes in the database, you could use the id from TableB, or a composition of id's in TableA and TableB. If you do not need to update, you could map the id field to a different Solr field and let Solr auto-generate the unique id.

Related

Odoo 13 How to show some field only in Customers Accounting module [duplicate]

This question already has an answer here:
How to create Customer programmatically?
(1 answer)
Closed 2 years ago.
Customers are based on res.partner and not only Customers that based on res.partner vendor is based on res.partner too. Usually, when I add res.partner I will add a boolean field like IsMember to Identified the record is member, but I can't see any field to tell the difference between Customers and vendor. Because I want to Show some field only in Customer form.
<?xml version='1.0' encoding='utf-8'?>
<odoo>
<record model="ir.ui.view" id="partner_customer_form_view">
<field name="name">partner.customer</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//field[#name='phone']/.." position="after">
<field name="customer_group_id" />
</xpath>
<xpath expr="//field[#name='mobile']/.." position="before">
<field name="groupid"/>
<field name="member_id"/>
</xpath>
</field>
</record>
</odoo>
Odoo 13 uses Customer rank and Supplier rank this ranking base on the customer PO's and SO's, so if a customer has 1 PO then the vendor ranking will become 1 and the customer can be identified by supplier_rank > 0
supplier_rank = fields.Integer(default=0)
customer_rank = fields.Integer(default=0)
Remember this is an integer field so if you want to set someone customer by default you will set an integer value, the higher the value the higher it will appear in the search list
so I guess this should work
<field name="customer_group_id" attrs="{'invisible': [('customer_rank' ,'>', 0)]}" />

how to create a method to display sales order id on basis of field selection in purchase order? sale order reference is already integrated in purchase

I have added a sales order reference in a purchase order form. I have also added one custom field in both sales and purchase forms. The field is "Trader name". I need the sale order reference field in the purchase order to display the sale order ID on the selection based on Trader Name.
I am selecting Trader Name while creating the sale order, and I want the sale order reference in the purchase order form to display the same sales order ID's linked with specific a Trader Name.
Example:
Sales order form-->trader name = abc--->so#200
purchase form--->selecting trader name "abc" and sale order reference field should automatically display all the sales order # under the selected Trader Name
NOTE: Trader Name field already fetched to purchase order form
on the basis of selected sales order id, it should also fetch the same order lines from sales order form
the code is in odoo 11
Here is my code:
*purchase_views.xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="purchase_order_form_inherit" model="ir.ui.view">
<field name="name">purchase.order.form.inherit</field>
<field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="arch" type="xml">
<field name="partner_ref" position="after">
<field name="x_trader_name"/>
<field name="sale_order_id"/>
</field>
</field>
*purchase.py
from odoo import models, fields
class PurchaseOrder(models.Model):
_inherit = 'purchase.order'
sale_order_id = fields.Many2one(
'sale.order',
"Sale Order",
help="Reference to Sale Order",
)
</record>
</odoo>
You need to filter your sale orders.
Add onchange method for trader name and fetch all related sale ordes then change the domain of sale_order_id to show only needed records.
You should return:
{'domain':{'sale_order_id':[('id','in',SO_IDS)]}}

sql alias to dictionary returns duplicate results

I have following class
<class name="Product" table="Product">
<id name="ID" />
...
<map name="CustomFields" table="CustomFieldView">
<key column="RECORDID" />
<map-key column="CFName" type="String" />
<element column="CFValue" type="String" />
</map>
</class>
and SP to select product with CustomFields dictionary
<sql-query name="GetProducts">
<return alias="p" class="Product" />
<return-join alias="cf" property="p.CustomFields" />
SELECT {p.*}, {cf.*}
FROM Product p
INNER JOIN CustomFieldView cf ON p.ID = cf.RECORDID
// WHERE
</sql-query>
when I select single product like WHERE ID = 1234, then it works as expected - returns one Product with populated CustomFields Dictionary property.
But when I select not single Product like WHERE ID IN (18780, 21642) or other criterias then I get Products duplicated 'CustomFields.Count' times, e.g. 2 Products and each has 20 Custom Fields, then 40 Products and each has 20 valid custom fields.
Do I missed something in mapping ?
You are returning a Cartesian product and therefore your product is being returned x times for every custom field.
To get around this problem you will need to use something like:-
var query = Session
.GetNamedQuery("GetProducts")
.SetResultTransformer(new DistinctRootEntityResultTransformer());
return query.List<Product>();
Please note that you will send all the data down the wire and NHibernate will perform the distinct transformer client (meaning web server or desktop app) side.
I am not 100% sure if the return join will be populated as I have never done things this way, you will need to test this.
edit
I think you fetching strategy is not quite right. Do you really need a <sql-query...> Could you use another strategy e.g. HQL?

NHibernate Criteria for a non-linked table

We are adding an attribute(tags) to a system. The attribute table is just a relation table without any foreign keys.
Is there a way to add to the criteria to generate a where clause for the attribute table on a parent table.
<class name="Account" table="dbo.Account" lazy="true" >
<id name="Id" column="`AccountId`">
<generator class="int"/>
</id>
<property name="Name" column="`Name`" />
<property name="Address" column="`Address`" />
</class>
<class name="Attribute" table="dbo.Attribute" lazy="true" >
<id name="Id" column="`AttributeId`">
<generator class="int"/>
</id>
<property name="Name" column="`Name`" />
<property name="LinkId" column="`LinkId`" />
<property name="Type" column="`Type`" />
</class>
Example Data
Account
1 - Person - Address
2 - Person - Address
Attribute
1 - Attrib1 - 1 - Account
2 - Attrib2 - 1 - Account
3 - Attrib1 - 2 - Account
4 - Attrib1 - 3 - Event
5 - Attrib1 - 4 - Location
Sample of Existing Code
ICriteria crit = session.CreateCriteria(typeof(Account));
crit.Add(Restrictions.Eq("Name", "Some"););
I would like to add the following to the where clause.
AccountId IN (SELECT LinkId FROM Attribute WHERE Name = 'Attrib1')
Why aren't you using an any type mapping for this? it does exactly this: referencing by a primary key and type name...
There might be some mistakes in the following piece of code, but it looks something like this:
DetachedCriteria subquery = DetachedCriteria.For<Attribute>()
.Add(Projections.Property("LinkId"))
.Add(Restrictions.Eq("Name", "Attrib1"))
.Add(Restrictions.Eq("Type", typeof(Account)));
ICriteria crit = session.CreateCriteria(typeof(Account));
.Add(Restrictions.Eq("Name", "Some"))
.Add(Subqueries.PropertyIn("id", subquery));

Extending the parent-child relationship

Given the one-table design given below how would the following best be queried
The set of extended family members given a folk id
The set of common ancestors given two folk ids
The set of descendants given a folk id
*Bonus 1st cousins, twice removed given a folk id
Table Folk
FolkID (PK)
MotherID (FK to folkid)
FatherID (FK to folkid)
Name
Gender
Someone has to build a familytree application?
I did something similar some time ago, using XML and XPath:
<Persons>
<Person ID="1" Name="Minu eesnimi" Surname="Minu perekonnanimi" Picture="0" Sex="M">
<Event Name="Birth" Prefix="" Location="Tallinn" Date="14.01.1963"><![CDATA["Ilusal jaanuarihommikul"]]>
</Event>
<Event Name="Death" Prefix="" Location="" Date=""/>
<Father ID="2" Type="Päris"/>
<Mother ID="3" Type="Päris"/>
<Spouse ID="4"/>
</Person>
...
String XPath="child::*/child::Person[child::Father[#ID=\""+String(ID)
+"\"] and child::Mother[#ID=\""+String(Spouse)+"\"]]";
etc.