All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.solr.common.SolrDocument Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.solr.common;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import org.apache.solr.common.util.NamedList;

/**
 * A concrete representation of a document within a Solr index. Unlike a lucene Document, a
 * SolrDocument may have an Object value matching the type defined in schema.xml
 *
 * 

For indexing documents, use the SolrInputDocument that contains extra information for document * and field boosting. * * @since solr 1.3 */ public class SolrDocument extends SolrDocumentBase implements Iterable> { protected final Map _fields; private List _childDocuments; public SolrDocument() { _fields = new LinkedHashMap<>(); } @Override public void writeMap(EntryWriter ew) throws IOException { _fields.forEach(ew.getBiConsumer()); } public SolrDocument(Map fields) { this._fields = fields; } /** * @return a list of field names defined in this document - this Collection is directly backed by * this SolrDocument. * @see #keySet */ @Override public Collection getFieldNames() { return this.keySet(); } /////////////////////////////////////////////////////////////////// // Add / Set / Remove Fields /////////////////////////////////////////////////////////////////// /** Remove all fields from the document */ @Override public void clear() { _fields.clear(); if (_childDocuments != null) { _childDocuments.clear(); } } /** Remove all fields with the name */ public boolean removeFields(String name) { return this.remove(name) != null; } /** * Set a field with the given object. If the object is an Array, it will set multiple fields with * the included contents. This will replace any existing field with the given name */ @Override public void setField(String name, Object value) { if (value instanceof Object[]) { value = new ArrayList<>(Arrays.asList((Object[]) value)); } else if (value instanceof Collection) { // nothing } else if (value instanceof NamedList) { // nothing } else if (value instanceof Iterable && !(value instanceof SolrDocumentBase)) { ArrayList lst = new ArrayList<>(); for (Object o : (Iterable) value) { lst.add(o); } value = lst; } _fields.put(name, value); } /** * This will add a field to the document. If fields already exist with this name it will append * value to the collection. If the value is Collection, each value will be added independently. * *

The class type of value and the name parameter should match schema.xml. schema.xml can be * found in conf directory under the solr home by default. * * @param name Name of the field, should match one of the field names defined under "fields" tag * in schema.xml. * @param value Value of the field, should be of same class type as defined by "type" attribute of * the corresponding field in schema.xml. */ @SuppressWarnings("unchecked") @Override public void addField(String name, Object value) { Object existing = _fields.get(name); if (existing == null) { if (value instanceof Collection) { Collection c = new ArrayList<>(3); for (Object o : (Collection) value) { c.add(o); } this.setField(name, c); } else { this.setField(name, value); } return; } Collection vals = null; if (existing instanceof Collection) { vals = (Collection) existing; } else { vals = new ArrayList<>(3); vals.add(existing); } // Add the values to the collection if (value instanceof Iterable && !(value instanceof SolrDocumentBase)) { for (Object o : (Iterable) value) { vals.add(o); } } else if (value instanceof Object[]) { for (Object o : (Object[]) value) { vals.add(o); } } else { vals.add(value); } _fields.put(name, vals); } /////////////////////////////////////////////////////////////////// // Get the field values /////////////////////////////////////////////////////////////////// /** returns the first value for a field */ public Object getFirstValue(String name) { Object v = _fields.get(name); if (v == null || !(v instanceof Collection)) return v; Collection c = (Collection) v; if (c.size() > 0) { return c.iterator().next(); } return null; } /** Get the value or collection of values for a given field. */ @Override public Object getFieldValue(String name) { return _fields.get(name); } /** Get a collection of values for a given field name */ @SuppressWarnings("unchecked") @Override public Collection getFieldValues(String name) { Object v = _fields.get(name); if (v instanceof Collection) { return (Collection) v; } if (v != null) { ArrayList arr = new ArrayList<>(1); arr.add(v); return arr; } return null; } @Override public String toString() { return "SolrDocument" + _fields; } /** Iterate of String->Object keys */ @Override public Iterator> iterator() { return _fields.entrySet().iterator(); } /** Beta API; may change at will. */ // TODO SOLR-15063 reconcile SolrDocumentBase/SolrDocument/SolrInputDocument debacle public void visitSelfAndNestedDocs(BiConsumer consumer) { consumer.accept(null, this); for (Entry keyVal : entrySet()) { final Object value = keyVal.getValue(); if (value instanceof SolrDocument) { consumer.accept(keyVal.getKey(), (SolrDocument) value); } else if (value instanceof Collection) { Collection cVal = (Collection) value; for (Object v : cVal) { if (v instanceof SolrDocument) { consumer.accept(keyVal.getKey(), (SolrDocument) v); } else { break; // either they are all SolrDocs, or none are } } } } if (_childDocuments != null) { for (SolrDocument childDocument : _childDocuments) { consumer.accept(null, childDocument); } } } // ----------------------------------------------------------------------------------------- // JSTL Helpers // ----------------------------------------------------------------------------------------- /** Expose a Map interface to the solr field value collection. */ public Map> getFieldValuesMap() { return new Map<>() { /** Get the field Value */ @Override public Collection get(Object key) { return getFieldValues((String) key); } // Easily Supported methods @Override public boolean containsKey(Object key) { return _fields.containsKey(key); } @Override public Set keySet() { return _fields.keySet(); } @Override public int size() { return _fields.size(); } @Override public boolean isEmpty() { return _fields.isEmpty(); } // Unsupported operations. These are not necessary for JSTL @Override public void clear() { throw new UnsupportedOperationException(); } @Override public boolean containsValue(Object value) { throw new UnsupportedOperationException(); } @Override public Set>> entrySet() { throw new UnsupportedOperationException(); } @Override public void putAll(Map> t) { throw new UnsupportedOperationException(); } @Override public Collection> values() { throw new UnsupportedOperationException(); } @Override public Collection put(String key, Collection value) { throw new UnsupportedOperationException(); } @Override public Collection remove(Object key) { throw new UnsupportedOperationException(); } @Override public String toString() { return _fields.toString(); } }; } /** Expose a Map interface to the solr fields. This function is useful for JSTL */ public Map getFieldValueMap() { return new Map<>() { /** Get the field Value */ @Override public Object get(Object key) { return getFirstValue((String) key); } // Easily Supported methods @Override public boolean containsKey(Object key) { return _fields.containsKey(key); } @Override public Set keySet() { return _fields.keySet(); } @Override public int size() { return _fields.size(); } @Override public boolean isEmpty() { return _fields.isEmpty(); } // Unsupported operations. These are not necessary for JSTL @Override public void clear() { throw new UnsupportedOperationException(); } @Override public boolean containsValue(Object value) { throw new UnsupportedOperationException(); } @Override public Set> entrySet() { throw new UnsupportedOperationException(); } @Override public void putAll(Map t) { throw new UnsupportedOperationException(); } @Override public Collection values() { throw new UnsupportedOperationException(); } @Override public Collection put(String key, Object value) { throw new UnsupportedOperationException(); } @Override public Collection remove(Object key) { throw new UnsupportedOperationException(); } @Override public String toString() { return _fields.toString(); } }; } // --------------------------------------------------- // MAP interface // --------------------------------------------------- @Override public boolean containsKey(Object key) { return _fields.containsKey(key); } @Override public boolean containsValue(Object value) { return _fields.containsValue(value); } @Override public Set> entrySet() { return _fields.entrySet(); } // TODO: Shouldn't the input parameter here be a String? The _fields map requires a String. @Override public Object get(Object key) { return _fields.get(key); } @Override public boolean isEmpty() { return _fields.isEmpty(); } @Override public Set keySet() { return _fields.keySet(); } @Override public Object put(String key, Object value) { return _fields.put(key, value); } @Override public void putAll(Map t) { _fields.putAll(t); } @Override public Object remove(Object key) { return _fields.remove(key); } @Override public int size() { return _fields.size(); } @Override public Collection values() { return _fields.values(); } @Override public void addChildDocument(SolrDocument child) { if (_childDocuments == null) { _childDocuments = new ArrayList<>(); } _childDocuments.add(child); } @Override public void addChildDocuments(Collection children) { for (SolrDocument child : children) { addChildDocument(child); } } @Override public List getChildDocuments() { return _childDocuments; } @Override public boolean hasChildDocuments() { boolean isEmpty = (_childDocuments == null || _childDocuments.isEmpty()); return !isEmpty; } @Override @Deprecated public int getChildDocumentCount() { if (_childDocuments == null) return 0; return _childDocuments.size(); } }