couchdb view that searches an array field for values passed in as a key array - view

I have some documents in couchdb that have fields that are arrays of id's for different associated documents:
{
associatedAssets: ["4c67f6241f4a0efb7dc2abc24a004dfe", "270fd4508a1222a1e2a27cbe7f002d9z"]
}
I would like to write a view that will let me pass in a key that is itself an array of ids, and then return documents whose associatedAssets fields contain one or more of the ids passed in via the key array e.g.
$.ajax({
url: "/db/_design/design_doc/_view/summaryByAssociatedAssets",
type: "post",
data: JSON.stringify({keys: ["4c67f6241f4a0efb7dc2abc24a004dfe", "6c67f6241f4a0efb7dc2abc24a004dfd"]}),
dataType: "json",
contentType: "application/json",
})
.done(function(resp){
console.log(resp[0]);
});
would return documents whose associatedAssets array contains one or more of the keys "4c67f6241f4a0efb7dc2abc24a004dfe", "6c67f6241f4a0efb7dc2abc24a004dfd".
I can't access the keys in my view, so I'm not sure if I can do this? Is there a better way to accomplish this?
Thanks!

Your view just needs to generate an output row per associatedAssets element, something like this:
function(doc) {
if( doc.associatedAssets ) {
for( var i=0, l=doc.associatedAssets.length; i<l; i++) {
emit( doc.associatedAssets[i], doc );
}
}
}
Then you'd need to adjust your call so it ends up passing that keys array as a query string parameter, which will return only the rows from the view that match keys in that array.
A total aside - assuming a recent CouchDB version, the best practices would be to replace doc in your emit with { _id: doc._id } and then use include_docs=true in your query so your view index doesn't get filled up (unnecessarily) with full documents.

In the view code you can access anything in the document itself, but there is no way to access any parameters that you pass in.
You could use temporary views that are generated for the specific query you are doing.
You could also use ElasticSearch instead. ElasticSearch has a much richer query DSL because that's the whole point of ElasticSearch. The CouchDB River allows you to automatically index all documents from CouchDB.
Using ElasticSearch, you could just search for any document whose associatedAssets contains any element from a list that you pass in.

Related

Filebeat Script Processor Event.Get All Fields In Log

I am looking to get all of the fields in a record in filebeat using the Script processor and perform an action on them. Using the event.Get() from the script processor, it says, "Get a value from the event (either a scalar or an object). If the key does not exist null is returned. If no key is provided then an object containing all fields is returned."
https://www.elastic.co/guide/en/beats/filebeat/current/processor-script.html
Therefore, my question is, what would I do to ensure that no key is provided to get an object that contains all of the fields are returned?
The event.Get() field will provide the top level fields. To look through these top level fields, use a for loop like:
- script:
lang: javascript
id: get_fields
source: >
function process(event) {
var a = event.Get();
for (var key in a) {
if(event.Get(key) == ""){
event.Delete(key);
}
}
}
I am unsure how to do this for nested fields in this way nor have I tried to extend it to nested fields, but this is how it works for now.

Is it possible to get data contained in another document by id, when map function is running for some document in couchbase view?

I have two kinds of documents in my couchbase bucket with keys like -
product.id.1.main
product.id.2.main
product.id.3.main
and
product.id.1.extended
product.id.2.extended
product.id.3.extended
I want to write a view for documents of first kind, such that when some conditions are matched for a document, I can emit the attributes contained in the documents of first kind as well as the document of second kind.
Something like -
function(doc, meta){
if((meta.id).match("product.id.*.main") && doc.attribute1.match("value1"){
var extendedDocId = replaceMainWithExtended(meta.id)
emit(meta.id, doc.attribute1 + getExtendedDoc(extendedDocId).extendedAttribute1 );
}
}
I want to know how to implement this kind of function in couchbase views -
getExtendedDoc(extendedDocId).extendedAttribute1

elastic4s bulk insert dont work with multiple elements in Json

Can someone please help me, how to execute bulk insert with header "Content-Type: application/x-ndjson" in elastic4s ? I have tried this
client.execute {
bulk(
indexInto("cars" / "car").source(getCarsFromJson)
).refresh(RefreshPolicy.WaitFor)
}.await
It works for one element in json, but when i add another element to json, no element are added to elastic.
Are you sure you are using the right syntax? Shouldn't it say
"cars/car"
Instead of
"cars" / "car"
The source method on indexInto will not support multiple json objects, because you're trying to put multiple documents inside a single document insert.
Instead, you will need to take your json, parse it into objects, and iterate over them adding an insert document for each one.
Something like the following:
def getCarsFromJson: Seq[String] = /// must return a sequence of json strings
val inserts = getCarsFromJson.map { car => indexInto("cars" /"car").source(car) }
client.execute {
bulk(inserts:_*).refresh(RefreshPolicy.WaitFor)
}

how to correctly render referenced entities in list when I have objects instead of numberic ids?

right now in order for the list to render properly I need to have this kind of data passed in:
row = {
id: value,
name: value,
height: value,
categories: [1,2,3,4]
}
how can I adapt the code so that a list works with this kind of data?
row = {
id: value,
name: value,
height: value,
categories: [{id: "1"},{id: "2"},{id: "3"},{id: "4"}]
}
when I try to do that it seems that it applies JSON.stringify to the objects so it is trying to find category with id [Object object]
I would to avoid a per case conversion of data as I do now..
it seems that I cannot do anything in my restClient since the stringify was already applied
I have the same issue when I fetch just one data row e.g in Edit or Create.. categories ReferenceArrayInput is not populated when categories contains objects
Have you tried using format?
https://marmelab.com/admin-on-rest/Inputs.html#transforming-input-value-tofrom-record
Might help transform your input value. Then you can use format() to change values back to the format your API expects.
If this does not work then you will have to probably create a custom component out of ReferenceArrayInput.

How do I get unique field values using rethinkdb javascript?

I have a field which has similar values. For eg {country : 'US'} occurs multiple times in the table. Similar for other countries too. I want to return an array which contains non-redundant values of 'country' field. I am new to creating Databases so likely this is a trivial question but I couldn't find anything useful in rethinkdb api.[SOLVED]
Thanks
You can use distinct, but the distinct command was created for short sequences only.
If you have a lot of data, you can use map/reduce
r.table("data").map(function(doc) {
return r.object(doc("country"), true) // return { <country>: true}
}).reduce(function(left, right) {
return left.merge(right)
}).keys() // return all the keys of the final document

Resources