Solr : How to Index a field in document as json field? - java

I know we can index a document as json but I want to index a field inside my document as json.
e.g.
{
id:"Person1",
name:"bob",
associatedCompanies:[
{
companyName:"apple",
companyId:"c1"
},
{
companyName:"google",
companyId:"c2"
}
]
}
I can have associatedCompanies field as an array by declaring it as multiValued in schema. But how can I add company element as json?
I don't think the parent-child example applies here since in this use case, the json element which is nested is not exactly same as the document. I just want to add some json element in my document.
Does anyone have any idea how this can be indexed? And how to query with such index? Is it possible to do query like below..
id:person AND name:bob AND associatedCompanies:[{
companyName:"apple",
companyId:"c1"
}]
or
id:person AND name:bob AND associatedCompanies:[{
companyName:"apple"
}]
In second query, will I get the response with the document having apple company?

Try out : Solr Nested Documents
and the Block Join Queries

Related

Spring Data MongoDB - projection and search

I am using "Wildcard text index" in order to search for a pattern in every fields of my class. I am also using projection in order to remove a certain field:
#Query(value = "{$text: { $search: ?0 }, fields = "{'notWantedField':0}")
However, I would like to prevent from matching something from the unwanted field.
In other words, I would like first to project (and remove fields), then search on the remaining fields.
Is there a way to combine projection and search while keeping the wildcard search?
Thanks a lot.
I am using spring-data-mongodb 1.10.8
A possible solution could be a $and operator combined with a $regex.
For example following the Mongodb documentation https://docs.mongodb.com/manual/reference/operator/query/text, if you suppose to create a text index combining subject and author (db.articles.createIndex({"author": "text", "subject": "text"}), you can exclude author field with this query:
db.articles.find( {$and: [{ $text: { $search: "coffee" } }, {"author": {'$regex' : '^((?!coffe).)*$', '$options' : 'i'}}]}, {"author": 0})
In your case, considering that your index is a wildcard, you must exclude, using the regex, all the fields that are also in the projection.

Query documents in MongoDB by object matching

How can I find the document that contains the a given JSON object?
Example:
suppose that in the database test there is a document like this:
{
"identification": {
"componentId": "3a4f6199-6141-4179-ac5f-f1bbcf627bb2",
"componentType": "PivotTable",
"dataDate": "2016-06-15T15:29:51.139+0200",
"dataType": "PTF",
"properties": {
"contextId": "0329fe70-92f0-4b60-b3c2-79377adb8f95",
"tags": ["tag1", "tag2"]
}
},
"viewData": {
"lineGroups": []
}
}
Now given only the identification part of the document with partial keys set with value:
{
"componentType": "PivotTable",
"properties": {
"tags": ["tag1"]
}
}
Since the above document's identification part is matching the given identification, then that document should be returned.
If I do db.test.find({identification: {/*the given identification segment*/}}), mongodb will compare directly the identification part by checking exactly every entry in the document. In this case that document will not be returned.
Is there a way in mongodb query language that allows me to do this in relatively straight forward or easy way? Or I have to parse the entries in Identification object recursively in order to construct a query?
Mongo will try to match WHOLE properties subdocument,
so in this case we will have to supply 1:1 document.
The way you could try to get this working is unwind every element and add it to query filter section.
{
"componentType": "PivotTable",
"properties.tags": {$in:["tag1"]}
}

Get matched index value of array in MongoDB Java

I am using mongodb with java and my documents looks like :
{
_id: ObjectId("abcd1234rf54")
createdDate: "12/11/15"
type: 1
nameIdentity: [
{"name":"a"},
{"name":"b"},
{"name":"c"}
]
}
Where nameIdentity is an array of name documents. I am trying to query on name and find out index of matched document.
For eg: my query is Document resultDocument = mongoDatabase.getCollection(test).find(new Document("nameIdentity.name","b")).first();.
When this query is executed it gives me the result document/matched document. But what I also want is the index of the result document. I mean at what index there is a match. Is this possible in this approach or is there some other way to do so. Any suggestions are highly appreciated.

mongoDB: $inc of a nonexistent document in an array

I was not able to write a code, which would be able to increment a non-existent value in an array.
Let's consider a following structure in a mongo collection. (This is not the actual structure we use, but it maintains the issue)
{
"_id" : ObjectId("527400e43ca8e0f79c2ce52c"),
"content" : "Blotted Science",
"tags_with_ratings" : [
{
"ratings" : {
"0" : 6154,
"1" : 4974
},
"tag_name" : "math_core"
},
{
"ratings" : {
"0" : 154,
"1" : 474,
},
"tag_name" : "progressive_metal"
}
]
}
Example issue: We want to add to this document into the tags_with_ratings attribute an incrementation of a rating of a tag, which is not yet added in the array. For example we would want to increment a "0" value for a tag_name "dubstep".
So the expected behaviour would be, that mongo would upsert a document like this into the "tags_with_ratings" attribute:
{
"ratings" : {
"0" : 1
},
"tag_name" : "dubstep"
}
At the moment, we need to have one read operation, which checks if the nested document for the tag is there. If it's not, we pull the array tags_with_ratings out, create a new one, re-add the values from the previous one and add the new nested document in there. Shouldn't we be able to do this with one upsert operation, without having the expensive read happen?
The incrementation of the values takes up 90% of the process and more than half of it is consumed by reading, because we are unable to use $inc capability of creating an attribute, if it is non-existent in the array.
You cannot achieve what you want with one step using this schema.
You could do it however if you used tag_name as the key name instead of using ratings there, but then you may have a different issue when querying.
If the tag_name value was the field name (replacing ratings) you'd have {"dubstep":{"0":1}} instead of { "ratings" : {"0" : 1},"tag_name" : "dubstep"} which you can update dynamically the way you want to. Just keep in mind that this schema will make it more difficult to query - you have to know what the ratings are in advance to be able to query by keyname.

How to create nested document in Solr indexing?

I want to create nested document in solr, I am using java/GWT/SolrJ.
Currently I am indexing following fields:
Items:
id title desc.
1 xyz xyzxyzxyz
2 pqr pqrpqrpqr
3 abc abcabcabc.
But now i want to create one more document linked with each document from above i.e. for id 1 there is one subdocument which contains follwing fields:
Item_User_Details:
for item 1 :
user details
1 qweqweqwe
2 xyzxyzxyz
3 asdasdasd
in this way I want to create for each item id from above table, there is one linked document of item_user_details.
How can I do this...?
Thanks in advance...
In our schema we've a lot of related tables.
We decided to flatten all relations into one document. To achieve this we created a custom importer (using SolrJ), which loads each document from the index, adds the related fields and write that document back.
[edit]
We do this in the following way:
export the data in a csv-file for each table (item, item_user_details)
import each csv-file into Solr, starting with the top (item in your case)
Start an Embedded-Solr server:
System.setProperty("solr.solr.home", config.getSolrIndexPath());
CoreContainer.Initializer initializer = new CoreContainer.Initializer();
this.coreContainer = initializer.initialize();
this.solr = new EmbeddedSolrServer(this.coreContainer, "");
Alternatively you can access a remote solr instance:
this.solr = new HttpSolrServer("http://[your-url]/solr");
Create a SolrDocument for each line in the file
add it to the index this.solr.add(ClientUtils.toSolrInputDocument(doc));
Commit this.solr.commit();
Load documents from the index (items)
Idetify relations in the csv-file for item_user_details via the document id (item-id)
Exted the loaded document with the fields from item_user_details
Commit the Document again

Categories