def to_es14_script(self, schema, not_null=False, boolean=False, many=True):
    if not self.terms:
        return NULL.to_es14_script(schema)

    v = self.terms[-1]
    acc = FirstOp("first", v).partial_eval().to_es14_script(schema)
    for v in reversed(self.terms[:-1]):
        m = v.missing().partial_eval()
        e = NotOp("not", m).partial_eval().to_es14_script(schema)
        r = FirstOp("first", v).partial_eval().to_es14_script(schema)

        if r.miss is TRUE:
            continue
        elif r.miss is FALSE:
            acc = r
            continue
        elif acc.type == r.type:
            new_type = r.type
        elif acc.type == NUMBER and r.type == INTEGER:
            new_type = NUMBER
        elif acc.type == INTEGER and r.type == NUMBER:
            new_type = NUMBER
        else:
            new_type = OBJECT

        acc = EsScript(
            miss=AndOp("and", [acc.miss, m]).partial_eval(),
            type=new_type,
            expr="(" + e.expr + ") ? (" + r.expr + ") : (" + acc.expr + ")",
            frum=self
        )
    return acc
 def _convert(v):
     if v is None:
         return NULL.to_es14_script(schema)
     if v is True:
         return EsScript(
             type=BOOLEAN,
             expr="true",
             frum=self
         )
     if v is False:
         return EsScript(
             type=BOOLEAN,
             expr="false",
             frum=self
         )
     if isinstance(v, text_type):
         return EsScript(
             type=STRING,
             expr=quote(v),
             frum=self
         )
     if isinstance(v, int):
         return EsScript(
             type=INTEGER,
             expr=text_type(v),
             frum=self
         )
     if isinstance(v, float):
         return EsScript(
             type=NUMBER,
             expr=text_type(v),
             frum=self
         )
     if isinstance(v, dict):
         return EsScript(
             type=OBJECT,
             expr="[" + ", ".join(quote(k) + ": " + _convert(vv) for k, vv in v.items()) + "]",
             frum=self
         )
     if isinstance(v, (list, tuple)):
         return EsScript(
             type=OBJECT,
             expr="[" + ", ".join(_convert(vv).expr for vv in v) + "]",
             frum=self
         )
def to_es14_script(self, schema, not_null=False, boolean=False, many=True):
    if self.var == ".":
        return "_source"
    else:
        if self.var == "_id":
            return EsScript(type=STRING, expr='doc["_uid"].value.substring(doc["_uid"].value.indexOf(\'#\')+1)', frum=self)

        columns = schema.values(self.var)
        acc = []
        for c in columns:
            varname = c.es_column
            frum = Variable(c.es_column)
            q = quote(varname)
            if many:
                acc.append(EsScript(
                    miss=frum.missing(),
                    type=c.jx_type,
                    expr="doc[" + q + "].values" if c.jx_type != BOOLEAN else "doc[" + q + "].value==\"T\"",
                    frum=frum,
                    many=True
                ))
            else:
                acc.append(EsScript(
                    miss=frum.missing(),
                    type=c.jx_type,
                    expr="doc[" + q + "].value" if c.jx_type != BOOLEAN else "doc[" + q + "].value==\"T\"",
                    frum=frum,
                    many=True
            ))

        if len(acc) == 0:
            return NULL.to_es14_script(schema)
        elif len(acc) == 1:
            return acc[0]
        else:
            return CoalesceOp("coalesce", acc).to_es14_script(schema)