Mongodb Java nested update - mongodb-java

I have a MongoDB document structure like this
{
"_id": "002",
"list": [
{
"year": "2015",
"entries": [{...}, {...}]
},
{
"year": "2014",
"entries": [{...}, {...}]
}
]
}
I want to push a new element into "entries". I know it is possible using
collection.updateOne(
Filters.eq("_id", "002"),
new Document("$push", new Document("list.0.entries", "{...}")
);
But this appends to "entries" of the 1st element of "list". I want to append to "entries" for the "year" 2015. How can I do this with MongoDB Java driver API (3.0)?

I think you should use something like
Filters.and(Filters.eq("_id", "002"), Filters.eq("list.year", "2015"))
PS As the Filters javadoc suggests, it's convenient to use static import for it (to make it less verbose by skipping the "Filters." part)

You can use
Bson filter = Filters.and(Filters.eq("_id", "002"), Filters.eq("list", Filters.eq($elemMatch, Filters.eq("year", "2015"))
Document list = collection.find().filter(filter)
Afterwards you can iterate through the list to find the year 2015 and get the entries for this one and insert the new element via java code. Keep the updated list in a local variable and write this one through an update command into your mongoDB.

Related

Elastic/Opensearch: HowTo create a new document from an _ingest/pipeline

I am working with Elastic/Opensearch and want to create a new document in a different index out of an _ingest/pipeline
I found no help in the www...
All my documents (filebeat) get parsed and modified in the beginning by a pipline, lets say "StartPipeline".
Triggered by an information in a field of the incoming document, lets say "Start", I want to store that value in a special way by creating a new document in a different long-termindex - with some more information from the triggering document.
If found possibilities, how to do this manually from the console (update_by_query / reindex / painlesscripts) but it has to be triggered by an incoming document...
Perhaps this is easier to understand - in my head it looks like something like that.
PUT _ingest/pipeline/StartPipeline
{
"description" : "create a document in/to a different index",
"processors" : [ {
"PutNewDoc" : {
"if": "ctx.FieldThatTriggers== 'start'",
"index": "DestinationIndex",
"_id": "123",
"document": { "message":"",
"script":"start",
"server":"alpha
...}
}
} ]
}
Does anyone has an idea?
And sorry, I am no native speaker, I am from Germany

How do I use FreeFormTextRecordSetWriter

I my Nifi controller I want to configure the FreeFormTextRecordSetWriter, but I have no Idea what I should put in the "Text" field. I'm getting the text from my source (in my case GetSolr), and just want to write this, period.
Documentation and mailinglist do not seem to tell me how this is done, any help appreciated.
EDIT: Here the sample input + output I want to achieve (as you can see: not ransformation needed, plain text, no JSON input)
EDIT: I now realize, that I can't tell GetSolr to return just CSV data - but I have to use Json
So referencing with attribute seems to be fine. What the documentation omits is, that the ${flowFile} attribute should containt the complete flowfile that is returned.
Sample input:
{
"responseHeader": {
"zkConnected": true,
"status": 0,
"QTime": 0,
"params": {
"q": "*:*",
"_": "1553686715465"
}
},
"response": {
"numFound": 3194,
"start": 0,
"docs": [
{
"id": "{402EBE69-0000-CD1D-8FFF-D07756271B4E}",
"MimeType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"FileName": "Test.docx",
"DateLastModified": "2019-03-27T08:05:00.103Z",
"_version_": 1629145864291221504,
"LAST_UPDATE": "2019-03-27T08:16:08.451Z"
}
]
}
}
Wanted output
{402EBE69-0000-CD1D-8FFF-D07756271B4E}
BTW: The documentation says this:
The text to use when writing the results. This property will evaluate the Expression Language using any of the fields available in a Record.
Supports Expression Language: true (will be evaluated using flow file attributes and variable registry)
I want to use my source's text, so I'm confused
You need to use expression language as if the record's fields are the FlowFile's attributes.
Example:
Input:
{
"t1": "test",
"t2": "ttt",
"hello": true,
"testN": 1
}
Text property in FreeFormTextRecordSetWriter:
${t1} k!${t2} ${hello}:boolean
${testN}Num
Output(using ConvertRecord):
test k!ttt true:boolean
1Num
EDIT:
Seems like what you needed was reading from Solr and write a single column csv. You need to use CSVRecordSetWriter. As for the same,
I should tell you to consider to upgrade to 1.9.1. Starting from 1.9.0, the schema can be inferred for you.
otherwise, you can set Schema Access Strategy as Use 'Schema Text' Property
then, use the following schema in Schema Text
{
"name": "MyClass",
"type": "record",
"namespace": "com.acme.avro",
"fields": [
{
"name": "id",
"type": "int"
}
]
}
this should work
I'll edit it into my answer. If it works for you, please choose my answer :)

elasticsearch can't understand signed date

I'm trying to save a document with the current values on Elasticsearch (1.7) from my ruby script.
{
"P577 ": [{
"snaktype": "value",
"property": "P577",
"hash": "2a7ea4b81277334f08c4cd9efbce76001505a481",
"datavalue": {
"value": {
"time": "+2015-10-16T00:00:00Z",
"timezone": 0,
"before": 0,
"after": 0,
"precision": 11,
"calendarmodel": "http://www.wikidata.org/entity/Q1985727"
},
"type": "time"
},
"datatype": "time"
}]
}
turns out that ES don't know how to handle with the time (+2015-10-16T00:00:00Z).
Is there a way to make ES understand this kind of date?
I know I can maybe using mapping, but what I showed is a very small piece of a giant JSON, with lots of nested nodes (like here)
Unfortunately, the only way to do this is with a custom mapping and changing how ES detects dates:
What I've done in the past is to
Insert a document.
Extract the mapping (see how here).
Update the mapping to my liking.
Do a PUT of the new mapping... And to do this, you might need to create a different type, as sometimes ES cannot replace a mapping on the fly.
I've never done this with dates, but had to do it a few times with the way a field is indexed.
"+2015-10-16T00:00:00Z" remove plus sign and try it,.
"2015-10-16T00:00:00Z"

RestKit 2.0 - Mapping json array to an enity relationship loses array sequence

I have a problem mapping json to CoreData and reading it out again. I map from json to an Activity-Entity with a relationship of last participant entities. The last_particpants is an array with the most recent participants, ordered from most recent first by the API.
{
"id": 50,
"type": "Initiative",
"last_participants": [
{
"id": 15,
"first_name": "Chris",
},
{
"id": 3,
"first_name": "Mary",
},
{
"id": 213,
"first_name": "Dany",
}
]
}
I have RestKit logging on and see that the mapping reads the array elements one by one and keeps the order. However CoreData saves them as an NSSet of entities and then the order gets lost. When I read out the data its is mixed up. What options do I have to keep the order in which the array was mapped? Any help would be great.
2 options:
Use an ordered set in Core Data (set on the attribute in the properties inspector).
Use the #metadata provided by RestKit to access the collection order during mapping.

Find matching array items in MongoDB document

I am developing a web app using Codeigniter and MongoDB.
In the database I got a document that look like this:
{
"_id": {
"$id": "4f609932615a935c18r000000"
},
"basic": {
"name": "The project"
},
"members": [
{
"user_name": "john",
"role": "user",
"created_at": {
"sec": 1331730738,
"usec": 810000
}
},
{
"user_name": "markus",
"role": "user",
"created_at": {
"sec": 1331730738,
"usec": 810000
}
}
]
}
I need to search this document using both user_name and role. Right now when I am using the below code I get both. I only want to get array items matching both user_name and role.
$where = array (
'_id' => new MongoId ($account_id),
'members.user_id' => new MongoId ($user_id),
'members.role' => $role
);
$this -> cimongo -> where ($where) -> count_all_results ('accounts');
This is an old question, but as of MongoDB 2.2 or so you can use the $ positional operator in a projection so that only the matched array element is included in the result.
So you can do something like this:
$this->cimongo->where($where)->select(array('members.$'))->get('accounts');
This is a repeat of this question:
Get particular element from mongoDB array
Also you might want to use $elemMatch
http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-ValueinanArray
Here is the rub -- you aren't going to be able to get the array items that match because mongo is going to return the entire document if those elements match. You will have to parse out the code client side. Mongo doesn't have a way to answer, "return only the array that matches."

Resources