Skip to content

Instantly share code, notes, and snippets.

@chrismcg
Created December 6, 2012 10:38
Show Gist options
  • Select an option

  • Save chrismcg/4223574 to your computer and use it in GitHub Desktop.

Select an option

Save chrismcg/4223574 to your computer and use it in GitHub Desktop.

I'm struggling with a problem related to using partial_fields and nested data. The examples below are a simplification of my actual problem but are enough I hope to demonstrate it.

Say I'm building a CMS and it supports multiple languages. In the editor for this CMS I'd like to show all the content the user can access and this access is restricted by the locales they can see and whether a particular piece of content has been set as visible yet.

Below are two ways I tried unsuccessfully to map this. Am I going to need to use parent/child documents?

curl -XDELETE 'http://localhost:9201/test_cms'

curl -XPUT 'http://localhost:9201/test_cms'

curl -XPUT 'http://localhost:9201/test_cms/document/_mapping' -d '{
  "document" : {
    "properties": {
      "name": { "type": "string" },
      "content": {
        "type": "nested",
        "properties": {
          "locale": { "type": "string" },
          "visible": { "type": "boolean" },
          "data": { "type": "string" }
        }
      }
    }
  }
}'

curl -XPUT 'http://localhost:9201/test_cms/document/1' -d '{
  "name": "Some Name",
  "content": [
    {
      "locale": "en",
      "visible": true,
      "data": "Some english content"
    },
    {
      "locale": "es",
      "visible": true,
      "data": "Some spanish content"
    },
    {
      "locale": "fr",
      "visible": false,
      "data": "Some french content"
    }
  ]
}'

curl -XPUT 'http://localhost:9201/test_cms/document/2' -d '{
  "name": "Some Other Name",
  "content": [
    {
      "locale": "en",
      "visible": true,
      "data": "Some other english content"
    },
    {
      "locale": "es",
      "visible": true,
      "data": "Some other spanish content"
    },
    {
      "locale": "fr",
      "visible": true,
      "data": "Some other french content"
    }
  ]
}'

curl -XGET 'http://localhost:9201/test_cms/_search?pretty=true' -d '{
  "query": {
    "nested": {
      "path": "content",
      "query": {
        "filtered": {
          "filter": {
            "bool" : {
              "must" : [
                { "term": { "visible": true }},
                { "terms": { "locale": ["en", "fr"] }}
              ]
            }
          },
          "query": {
            "query_string": {
              "fields": [
                "data"
              ],
              "query": "other"
            }
          }
        }
      }
    }
  }
}'

How can I remove a nested content based on locale or visibility or not having content matching the search? The output is:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.8465736,
    "hits" : [ {
      "_index" : "test_cms",
      "_type" : "document",
      "_id" : "2",
      "_score" : 0.8465736, "_source" : {
  "name": "Some Other Name",
  "content": [
    {
      "locale": "en",
      "visible": true,
      "data": "Some other english content"
    },
    {
      "locale": "es",
      "visible": true,
      "data": "Some other spanish content"
    },
    {
      "locale": "fr",
      "visible": true,
      "data": "Some other french content"
    }
  ]
}
    } ]
  }
}

In this case I'd like it to be

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.8465736,
    "hits" : [ {
      "_index" : "test_cms",
      "_type" : "document",
      "_id" : "2",
      "_score" : 0.8465736, "_source" : {
  "name": "Some Other Name",
  "content": [
    {
      "locale": "en",
      "visible": true,
      "data": "Some other english content"
    },
    {
      "locale": "fr",
      "visible": true,
      "data": "Some other french content"
    }
  ]
}
    } ]
  }
}

I.e. the spanish locale removed as it wasn't included in the filter

If I arrange the data as below I can use partial_fields but only for the locale, I can't specify visible for example. Also I have to list out the fields explicitly in the query

curl -XDELETE 'http://localhost:9201/test_cms'

curl -XPUT 'http://localhost:9201/test_cms'

curl -XPUT 'http://localhost:9201/test_cms/document/_mapping' -d '{
  "document" : {
    "properties": {
      "name": { "type": "string" },
      "content": { "type": "nested" }
    },
    "dynamic_templates" : [
      {
        "visibility_template" : {
          "path_match": "content.*.visible",
          "mapping": { "type": "boolean" }
        }
      },
      {
        "data_template" : {
          "path_match": "content.*.data",
          "mapping": { "type": "string" }
        }
      }
    ]
  }
}'

curl -XPUT 'http://localhost:9201/test_cms/document/1' -d '{
  "name": "Some Name",
  "content": [
    {
      "en" : {
        "visible": true,
        "data": "Some en content"
      }
    },
    {
      "es" : {
        "visible": true,
        "data":  "Some es content"
      }
    },
    {
      "fr" : {
        "visible": false,
        "data": "Some fr content"
      }
    }
  ]
}'

curl -XPUT 'http://localhost:9201/test_cms/document/2' -d '{
  "name": "Some Other Name",
  "content": [
    {
      "en" : {
        "visible": true,
        "data": "Some other en content"
      }
    },
    {
      "es" : {
        "visible": true,
        "data": "Some other es content"
      }
    },
    {
      "fr" : {
        "visible": true,
        "data": "Some other fr content"
      }
    }
  ]
}'

curl -XGET 'http://localhost:9201/test_cms/_search?pretty=true' -d '{
  "partial_fields" : {
    "partial" : { "exclude": ["content.es"] }
  },
  "query" : {
    "nested" : {
      "path": "content",
      "query": {
         "query_string" : { 
           "fields": ["content.en.data", "content.fr.data"],
           "query": "other"
         }
        }
      }
    }
  }
}'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment