0

So here's an interesting problem that I couldn't manage to solve on my own.

I'm setting up a search index where I want my documents to contain several AtomField representing categories. Each document can have more than one category.

Google's documentation says that a Document can be setup with multiple fields using the same name, which is awesome, however, you can only specify the fields using the constructor, and you can't modify the field list after the Document is created.

The question is, how can I create the Document object with one field per category assuming my categories are in an array? I saw this answer in another question here in Stack Overflow (can't find it now), but this doesn't work correctly:

document = search.Document(
    doc_id = files[file_index],
    fields=[
        search.TextField(name='name', value=my_name),
        search.AtomField(name='category', value=c) for c in categories
    ])

I think the challenge here is more related with Python than with App Engine per se.

If the problem is not clear, I wrote a blog post with more details.

svpino
  • 1,864
  • 17
  • 18
  • Are you trying to do this: http://stackoverflow.com/questions/16409006/google-app-engine-using-search-api-python-with-list-fields ? – Ryan Sep 03 '14 at 13:18
  • No really. I'm trying to end up with multiple AtomFields, not only one field with multiple values. – svpino Sep 03 '14 at 14:03
  • Can you point out where in the documents documentation it is listed that you can have multiple same named fields? I don't see it, and I don't think it's doable, that's why they implemented the multiple-value fields. Why do you want to have categories in multiple AtomFields instead of one multiple values field? – Patrice Sep 03 '14 at 17:55
  • Field names do not have to be unique. A document can have multiple fields with the same name and same type, which is a way to represent a field with multiple values. https://developers.google.com/appengine/docs/python/search/ – svpino Sep 03 '14 at 19:17
  • Yeah, that is a comment on the "multi-valued fields" in the doc you linked. So what you are trying to do is to setup a multi-valued field.... which in the end is doable following the link bruyere provided (didn't test it personally but the solution has been accepted, so I guess it works). Unless I'm misunderstanding your question – Patrice Sep 03 '14 at 19:24
  • The solution was accepted, but the answer doesn't work correctly. – svpino Sep 04 '14 at 18:15

2 Answers2

2

I'm not sure this is what you're asking for, but it sounds like you just want to be able to concatenate two lists:

document = search.Document(
    doc_id = files[file_index],
    fields =
        [ search.TextField(name='name', value=my_name) ]
        + [ search.AtomField(name='category', value=c) for c in categories ]
    )
Lasse
  • 86
  • 2
  • How is this different from the original code that I mentioned doesn't work? – svpino Sep 04 '14 at 18:20
  • @svpino That this is syntactically correct? If this is not what you're looking for then please elaborate on "doesn't work correctly". – Lasse Sep 04 '14 at 21:06
  • This is the error I get when executing: 'list' object has no attribute 'name' Traceback (most recent call last): File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1529 – svpino Sep 04 '14 at 22:25
  • It doesn't sound like it has anything to do with the code you showed. Maybe show a minimal example of the code that fails. – Lasse Sep 05 '14 at 03:01
  • It could be that you are providing a list of fields as a field. You need to change `[ field0, list_of_fields ]` to `[ field0 ] + list_of_fields`. – Lasse Sep 05 '14 at 03:14
  • Nevermind @Lasse. I'm an idiot. Your answer is the right one. I was setting up the array the wrong way. Thanks a lot! – svpino Sep 05 '14 at 13:39
  • @svpino Just looked up your blog. You can simplify your code by doing this `[ field0, field1 ] + list_of_fields` instead of `[ field0 ] + [ field1 ] + list_of_fields`. – Lasse Sep 05 '14 at 21:23
  • Better yet! Thanks! I'm definitively not a Python guy. – svpino Sep 06 '14 at 15:23
0

You can include more than one instance of an AtomField with a given name in the fields array:

document = search.Document(
  doc_id = article["id"],
    fields=[
      search.TextField(name='title', value=article["title"]),
      search.DateField(name='date', value=article["date"]),                 
      search.HtmlField(name='content', value=article["html"]),
      search.AtomField(name='tag', value='Foo'),
      search.AtomField(name='tag', value='Bar')
    ])
Alan
  • 690
  • 3
  • 6
  • This is not the solution since tags are dynamically coming from a list. I don't have them to specify each one of the AtomFields. – svpino Sep 04 '14 at 18:14