How to get other documents' data by document id in map function - join

I have a problem "joining" some documents in a view. Here's my schema: Documents with type "category" can hold an embedded array of ids to documents with type "page". Both have a field "name".
My Documents:
{
"_id": "887c28dcf6dd8429d404d276b900b203",
"_rev": "3-c4d1e0c8378bb0081b5fe3522ee649a0",
"TYPE": "category",
"NAME": "Home",
"PAGES": [
{"PAGE_ID": "887c28dcf6dd8429d404d276b900ad8f"},
{"PAGE_ID": "887c28dcf6dd8429d404d276b900b203"},
{"PAGE_ID": "887c28dcf6dd8429d404d276b900bae0"}
]
}
{
"_id": "887c28dcf6dd8429d404d276b9008c01",
"_rev": "1-afd54c654ae5afa56a3fbd7b1ba119d2",
"TYPE": "page",
"NAME": "Foo"
}
Now I want to join these in a view with this map function:
function(doc) {
if (doc.TYPE == "category") {
for (id in doc.PAGES) {
emit(doc.NAME, doc.PAGES[id].PAGE_ID);
}
}
}
But instead of the PAGE_ID I want the NAME of the referencing document.
This is basically the example from the CouchDB wiki, but they don't show the map function. So any ideas?

You need to include a _id field somewhere in your output value. After that, you use include_docs=true and the view will include the linked document instead of the source document. For example:
function(doc) {
if (doc.TYPE == "category") {
for (var x = 0; x < doc.PAGES.length; x++) {
emit(doc.NAME, { _id: doc.PAGES[x].PAGE_ID });
}
}
}
When you query this view, you add include_docs=true to your URL. And your view output will add a new field to each row called doc. Ordinarily, that field will contain the full source document. In this case, it will include the linked document you are referring to.
EDIT Btw, you're using the for...in loop incorrectly. A for...in is used to loop over the properties of an object. You need to use a simple for loop to iterate an array like this.

Related

Elasticsearch saves document as string of array, not array of strings

I am trying to contain array as a document value.
I succeed it in "tags" field as below;
This document contains array of strings.
curl -XGET localhost:9200/MY_INDEX/_doc/132328908
#=> {
"_index":"MY_INDEX",
"_type":"_doc",
"_id":"132328908",
"found":true,
"_source": {
"tags": ["food"]
}
}
However, when I am putting items in the same way as above,
the document is SOMETIMES like that;
curl -XGET localhost:9200/MY_INDEX/_doc/328098989
#=> {
"_index":"MY_INDEX",
"_type":"_doc",
"_id":"328098989",
"found":true,
"_source": {
"tags": "[\"food\"]"
}
}
This is string of array, not array of strings, which I expected.
"tags": "[\"food\"]"
It seems that this situation happens randomly and I could not predict it.
How could it happen?
Note:
・I use elasticsearch-ruby client to index a document.
This is my actual code;
es_client = Elasticsearch::Client.new url: MY_ENDPOINT
es_client.index(
index: MY_INDEX,
id: random_id, # defined elsewhere
body: {
doc: {
"tags": ["food"]
},
}
)
Thank you in advance.

Searchkick: how to save records in ElasticSearch in different indices based on record timestamp?

I have a Rails Model with Searchkick.
I want my model instances to be saved in ElasticSearch in different indices based on the month creation of the instance.
Lets say I have the following instances in my Model:
A created the 03/25/2021
B created the 03/28/2021
C created the 04/01/2021
Instead of having one ES index (which is the default behavior for Searchkick), how can I store when my instances are created:
A & B in ES index labeled: model_2021_03
C in ES index labeled: model_2021_04
From what I understand, there are two main steps:
Create Multiple Index(indices)
Store the document in one of those index.
Idea here is making the index as "Write_Index" in which you want to put the document and mark others as "Read_Index".
So you can start with:
1. Creating an Index Template.
PUT /_index_template/model_template
{
"index_patterns": [
"model*"
],
"priority": 1,
"template": {
"aliases": {
"model":{}
},
"mappings": {
"dynamic":"strict",
"_source":
{"enabled": false},
"properties": {
//your filed mappings here
}
},
"settings": {
"index": {
"number_of_shards": 1,
"number_of_replicas": 3
}
}
}
}
2.Create an index for a particular month,which will follow the model template(in step 1) with an naming strategy in your code
PUT model_YYYY_MM
Ex: lets say, you create two index model_2021_03, model_2021_04, now you want to store the documents in one of them,
Idea here is to mark the index, that you want to store the document in
as "Write_Index" and all other as "Read_Index", so when you store the
document using alias name("model") here, it will get stored in write
index by default.
3. Making the index as write index and others as read
POST /_aliases
{
"actions": [
{"add":
{"index": "model_2021_04",
"alias": "model",
"is_write_index": true}
},
{"add":
{"index": "model_2021_03",
"alias": "model",
"is_write_index": false}
}
]
}
4.Finally putting documents in index using alias name
PUT /model/_doc/1
{
//your data here
}

Nested query GraphQL : Syntax error - iOS

I am working with Apollo GraphQL and have to call nested query .But while call the Query in .graphql file it showing
Syntax error : Expected Name, found {
Let me know how to call Nested query of GraphQL.
I have to call getAllproduct{....} query with the specified parameters.Here the FilterInput having the parameter as location with another pattern of query , so I don't know how to call this nested query.Anyone please help me to find out the solution.Thanks...
If an argument is an Input Object Type (as opposed to a Scalar), you can include the fields of the Input Object Type by using curly brackets.
query MyProductsQuery {
allProducts(
pageNumber: "someString"
filter: {
title: "someOtherString"
yearFrom: 1900
location: {
city: "yetAnotherString"
state: "FL"
}
}
) {
id
# other product fields
}
}
Of course, hardcoding those values in a .graphql file is not very helpful. You probably want to be able to swap those values out programatically. So here's what that same query looks like with variables:
query MyProductsQuery($pageNumber: String, $filter: FilterInput) {
allProducts(pageNumber: $pageNumber, filter: $filter) {
id
# other product fields
}
}
Your variables are passed in separately from your query and unlike your query, are not a GraphQL document. They are just JSON:
{
"pageNumber": "someString",
"filter": {
"title": "someOtherString",
"yearFrom": 1900,
"location": {
"city": "yetAnotherString",
"state": "FL"
}
}
}

Rails PSQL query JSON for nested array and objects

So I have a json (in text field) and I'm using postgresql and I need to query the field but it's nested a bit deep. Here's the format:
[
{
"name":"First Things",
"items":[
{
"name":"Foo Bar Item 1",
"price":"10.00"
},
{
"name":"Foo Item 2",
"price":"20.00"
}
]
},
{
"name":"Second Things",
"items": [
{
"name":"Bar Item 3",
"price":"15.00"
}
]
}
]
And I need to query the name INSIDE the items node. I have tried some queries but to no avail, like:
.where('this_json::JSON #> [{"items": [{"name": ?}]}]', "%#{name}%"). How should I go about here?
I can query normal JSON format like this_json::JSON -> 'key' = ? but need help with this bit.
Here you need to use json_array_elements() twice, as your top level document contains array of json, than items key has array of sub documents. Sample psql query may be the following:
SELECT
item->>'name' AS item_name,
item->>'price' AS item_price
FROM t,
json_array_elements(t.v) js_val,
json_array_elements(js_val->'items') item;
where t - is the name of your table, v - name of your JSON column.

Exclude fields from document in mongoid?

I have a Record model with many dynamic attributes. I want to make a request to the model an send the response as JSON to the client. But i want to exclude fields like _id and all foreign_keys in this model.
I found an interessting answer how to exclude the values of some keys: How do I exclude fields from an embedded document in Mongoid?, but the keys in the response still exists.
I got:
{
"_id": 1,
"name": "tom"
}
And the without method makes:
{
"_id": nil,
"name": "tom"
}
But i want:
{
"name": "tom"
}
Is it possible to remove or exclude some keys and the values from the result?
You don't want to remove fields from the mongoid document, what you want to do is remove fields from the generated json.
In your controller, do
render :json => #model.to_json(:except => :_id)
Documentation for the to_json method http://apidock.com/rails/ActiveRecord/Serialization/to_json
taken from the mongodb documentation at: http://docs.mongodb.org/manual/reference/method/db.collection.find/
Exclude Certain Fields from the Result Set
The following example selects documents that match a selection criteria and excludes a set of fields from the resulting documents:
db.products.find( { qty: { $gt: 25 } }, { _id: 0, qty: 0 } )
The query returns all the documents from the collection products where qty is greater than 25. The documents in the result set will contain all fields except the _id and qty fields, as in the following:
{ "item" : "pencil", "type" : "no.2" }
{ "item" : "bottle", "type" : "blue" }
{ "item" : "paper" }
i suppose mongoid is setting the _id attribute to nil since mongoid models have a defined set of attributes (even if they are dynamic, _id, _type etc are defined). maybe you can try it with the mongodb driver.
but i think RedXVII answer is the more practical way to go

Resources