Indexing and percolating documents with elasticsearch
I'm making and investigation for a seminar in retrieval information. I have a json
file with a list of articles and i need to index them and after use a percolator with highlighting.
The list of steps for do this in terminal is this:
1. Create a map with percolating.
curl -XPUT 'localhost:9200/my-index?pretty' -H 'Content-Type: application/json' -d'
{
"mappings": {
"_doc": {
"properties": {
"title": {
"type": "text"
},
"query": {
"type": "percolator"
}
}
}
}
}
'
Index a new article:
curl -XPUT 'localhost:9200/my-index/_doc/1?refresh&pretty' -H 'Content-Type: application/json' -d'
{
"CourseId":35,
"UnitId":12390,
"id":"16069",
"CourseName":"ARK102U_ARKEOLOJİK ALAN YÖNETİMİ",
"FieldId":8,
"field":"TARİH",
"query": {
"span_near" : {
"clauses" : [
{ "span_term" : { "title" : "dünya" } },
{ "span_term" : { "title" : "mirası" } },
{ "span_term" : { "title" : "sözleşmesi" } }
],
"slop" : 0,
"in_order" : true
}
}
}
'
Percolate a documment:
curl -XGET 'localhost:9200/my-index/_search?pretty' -H 'Content-Type: application/json' -d'
{
"query" : {
"percolate" : {
"field" : "query",
"document" : {
"title" : "Arkeoloji, arkeolojik yöntemlerle ortaya çıkarılmış kültürleri, dünya mirası sözleşmesi sosyoloji, coğrafya, tarih, etnoloji gibi birçok bilim dalından yararlanarak araştıran ve inceleyen bilim dalıdır. Türkçeye yanlış bir şekilde> "kazıbilim" olarak çevrilmiş olsa da kazı, arkeolojik araştırma yöntemlerinden sadece bir tanesidir."
}
}
},
"highlight": {
"fields": {
"title": {}
}
}
}
'
I have this code until now:
import json
from elasticsearch_dsl import (
DocType,
Integer,
Percolator,
Text,
)
# Read the json File
json_data = open('titles.json').read()
data = json.loads(json_data)
docs = data['response']['docs']
# Creating a elasticsearch connection
# connections.create_connection(hosts=['localhost'], port=['9200'], timeout=20)
"""
curl -XPUT 'localhost:9200/my-index?pretty' -H 'Content-Type: application/json' -d'
{
"mappings": {
"_doc": {
"properties": {
"title": {
"type": "text"
},
"query": {
"type": "percolator"
}
}
}
}
}
'
"""
class Documment(DocType):
course_id = Integer()
unit_id = Integer()
# title = Text()
id = Integer()
course_name = Text()
field_id = Integer()
field = Text()
class Meta:
index = 'titles_index'
properties={
'title': Text(),
'query': Percolator()
}
"""
"query": {
"span_near" : {
"clauses" : [
{ "span_term" : { "title" : "dünya" } },
{ "span_term" : { "title" : "mirası" } },
{ "span_term" : { "title" : "sözleşmesi" } }
],
"slop" : 0,
"in_order" : true
}
}
"""
for doc in docs:
terms = docs['title'].split(“ ”)
course_id = docs['CourseId']
unit_id = docs['UnitId']
id = docs['id']
course_name = docs['CourseName']
field_id = docs['FieldId']
field = docs['field']
UPDATE: Thank you for the answer, i have this now:
import json
from elasticsearch_dsl import (
connections,
DocType,
Mapping,
Percolator,
Text
)
from elasticsearch_dsl.query import (
SpanNear,
SpanTerm
)
from elasticsearch import Elasticsearch
# Read the json File
json_data = open('titles.json').read()
data = json.loads(json_data)
docs = data['response']['docs']
# creating a new default elasticsearch connection
connections.configure(
default={'hosts': 'localhost:9200'},
)
class Document(DocType):
title = Text()
query = Percolator()
class Meta:
index = 'title-index'
doc_type = '_doc'
def save(self, **kwargs):
return super(Document, self).save(**kwargs)
# create the mappings in elasticsearch
Document.init()
# index the query
for doc in docs:
terms = doc['title'].split(" ")
clauses = []
for term in terms:
field = SpanTerm(title=term)
clauses.append(field)
query = SpanNear(clauses=clauses)
item = Document(title=doc['title'],query=query)
item.save()
It is working fine, but i have two goals now:
elasticsearch.exceptions.AuthorizationException: TransportError(403,
'cluster_block_exception', 'blocked by: [FORBIDDEN/12/index read-only
/ allow delete (api)];')
I know i can solve this problem using this command: curl -XPUT -H "Content-Type: application/json" http://localhost:9200/_all/_settings -d '{"index.blocks.read_only_allow_delete": null}'
UPDATE Finally i solved it deleting the data folder.
But now i'm making search in the index and i don't get anything:
>>> text='Arkeoloji, arkeolojik yöntemlerle ortaya çıkarılmış kültürleri, dünya mirası sözleşmesi sosyoloji, coğrafya, tarih, etnoloji gibi birçok bilim dalından yararlanarak araştıran ve inceleyen bilim dalıdır. Türkçeye yanlış bir şekilde> "kazıbilim" olarak çevrilmiş olsa da kazı, arkeolojik araştırma yöntemlerinden sadece bir tanesidir.'
>>> s = Search().using(client).query("percolate", field='query', document={'title': text}).highlight('title')
>>> print(s.to_dict())
{'query': {'percolate': {'field': 'query', 'document': {'title': 'Arkeoloji, arkeolojik yöntemlerle ortaya çıkarılmış kültürleri, dünya mirası sözleşmesi sosyoloji, coğrafya, tarih, etnoloji gibi birçok bilim dalından yararlanarak araştıran ve inceleyen bilim dalıdır. Türkçeye yanlış bir şekilde> "kazıbilim" olarak çevrilmiş olsa da kazı, arkeolojik araştırma yöntemlerinden sadece bir tanesidir.'}}}, 'highlight': {'fields': {'title': {}}}}
>>> response = s.execute()
>>> response
<Response: {}>
And this is my trying with curl
:
curl -XGET 'localhost:9200/title-index/_search?pretty' -H 'Content-Type: application/json' -d '{
"query" : {
"percolate" : {
"field" : "query",
"document" : {
"title" : "Arkeoloji, arkeolojik yöntemlerle ortaya çıkarılmış kültürleri, dünya mirası sözleşmesi sosyoloji, coğrafya, tarih, etnoloji gibi birçok bilim dalından yararlanarak araştıran ve inceleyen bilim dalıdır. Türkçeye yanlış bir şekilde> "kazıbilim" olarak çevrilmiş olsa da kazı, arkeolojik araştırma yöntemlerinden sadece bir tanesidir."
}
}
},
"highlight": {
"fields": {
"title": {}
}
}
}'
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 0,
"max_score" : null,
"hits" : [ ]
}
}
I'm getting variable stats but not results:
>>> response.to_dict()
{'took': 9, 'timed_out': False, '_shards': {'total': 5, 'successful': 5, 'skipped': 0, 'failed': 0}, 'hits': {'total': 0, 'max_score': None, 'hits': []}}
>>> response
{'took': 12, 'timed_out': False, '_shards': {'total': 5, 'successful': 5, 'skipped': 0, 'failed': 0}, 'hits': {'total': 0, 'max_score': None, 'hits': []}}
>>> response
{'took': 12, 'timed_out': False, '_shards': {'total': 5, 'successful': 5, 'skipped': 0, 'failed': 0}, 'hits': {'total': 0, 'max_score': None, 'hits': []}}
Can anyone help me?
The first step is correct, ie the mapping is correct. But then, you need to first index a query, that's the whole point of percolation. So let's index your query:
curl -XPUT 'localhost:9200/my-index/_doc/my-span-query?refresh&pretty' -H 'Content-Type: application/json' -d '{
"query": {
"span_near" : {
"clauses" : [
{ "span_term" : { "title" : "dünya" } },
{ "span_term" : { "title" : "mirası" } },
{ "span_term" : { "title" : "sözleşmesi" } }
],
"slop" : 0,
"in_order" : true
}
}
}'
Then the idea is to find out which query would match the document you're percolating, so let's percolate a document:
curl -XGET 'localhost:9200/my-index/_search?pretty' -H 'Content-Type: application/json' -d '{
"query" : {
"percolate" : {
"field" : "query",
"document" : {
"title" : "Arkeoloji, arkeolojik yöntemlerle ortaya çıkarılmış kültürleri, dünya mirası sözleşmesi sosyoloji, coğrafya, tarih, etnoloji gibi birçok bilim dalından yararlanarak araştıran ve inceleyen bilim dalıdır. Türkçeye yanlış bir şekilde> "kazıbilim" olarak çevrilmiş olsa da kazı, arkeolojik araştırma yöntemlerinden sadece bir tanesidir."
}
}
},
"highlight": {
"fields": {
"title": {}
}
}
}'
And you would get this response with highlighting where you can see that my-span-query
matches the given document:
{
"took": 104,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.8630463,
"hits": [
{
"_index": "my-index",
"_type": "_doc",
"_id": "my-span-query",
"_score": 0.8630463,
"_source": {
"query": {
"span_near": {
"clauses": [
{
"span_term": {
"title": "dünya"
}
},
{
"span_term": {
"title": "mirası"
}
},
{
"span_term": {
"title": "sözleşmesi"
}
}
],
"slop": 0,
"in_order": true
}
}
},
"fields": {
"_percolator_document_slot": [
0
]
},
"highlight": {
"title": [
"Arkeoloji, arkeolojik yöntemlerle ortaya çıkarılmış kültürleri, <em>dünya</em> <em>mirası</em> <em>sözleşmesi</em> sosyoloji, coğrafya"
]
}
}
]
}
}
UPDATE
The same thing using elasticsearch-py-dsl
:
from elasticsearch_dsl import DocType, Text, Percolator
from elasticsearch import Elasticsearch
class Document(DocType):
title = Text()
query = Percolator()
class Meta:
index = 'my-index'
def save(self, ** kwargs):
return super(Document, self).save(** kwargs)
# 1a. create the mappings in elasticsearch
Document.init()
# 1b. or another alternative way of saving the mapping
query_mapping = elasticsearch_dsl.Mapping('_doc')
query_mapping.field('title', 'text')
query_mapping.field('query', 'percolator')
query_mapping.save('my-index')
# 2. index the query
query = Document(query={...your span query here...})
query.save()
# 3. send the percolate query
client = Elasticsearch()
response = client.search(
index="my-index",
body={
"query" : {
"percolate" : {
"field" : "query",
"document" : {
"title" : "Arkeoloji, arkeolojik yöntemlerle ortaya çıkarılmış kültürleri, dünya mirası sözleşmesi sosyoloji, coğrafya, tarih, etnoloji gibi birçok bilim dalından yararlanarak araştıran ve inceleyen bilim dalıdır. Türkçeye yanlış bir şekilde> "kazıbilim" olarak çevrilmiş olsa da kazı, arkeolojik araştırma yöntemlerinden sadece bir tanesidir."
}
}
},
"highlight": {
"fields": {
"title": {}
}
}
}
)
UPDATE 2
There's is no reason to also store the title
along with the query, you only need to store the query, so your code should look like this instead:
# index the query
for doc in docs:
terms = doc['title'].split(" ")
clauses = []
for term in terms:
field = SpanTerm(title=term)
clauses.append(field)
query = SpanNear(clauses=clauses)
item = Document(query=query) <-- change this line
item.save()
链接地址: http://www.djcxy.com/p/41438.html